@pallasoft/ps-file-components 2.4.0 → 2.4.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/components/ps-file-icon-button.js +1 -1
- package/dist/components/ps-file-list.js +1 -1
- package/dist/components/ps-file-picker.js +2 -1
- package/dist/components/ps-upload-row.js +1 -1
- package/dist/esm/components/ps-file-icon-button.js +1 -1
- package/dist/esm/components/ps-file-list.js +1 -1
- package/dist/esm/components/ps-file-picker.js +2 -1
- package/dist/esm/components/ps-upload-row.js +1 -1
- package/dist/esm/services/ps-image-text-service.js +2 -24
- package/dist/esm/services/ps-text-search-service.js +5 -75
- package/dist/esm/services/ps-xhr-upload-service.js +2 -1
- package/dist/models/ps-image-text-box.d.ts +2 -6
- package/dist/models/ps-image-text-layer.d.ts +2 -6
- package/dist/models/ps-image-text-word.d.ts +2 -5
- package/dist/models/ps-item-match-part.d.ts +2 -5
- package/dist/models/ps-item-match.d.ts +2 -4
- package/dist/models/ps-normalized-text.d.ts +2 -5
- package/dist/models/ps-search-item.d.ts +2 -4
- package/dist/models/ps-text-match.d.ts +2 -4
- package/dist/models/ps-text-segment.d.ts +2 -5
- package/dist/services/ps-image-text-service.js +2 -24
- package/dist/services/ps-text-search-service.js +5 -75
- package/dist/services/ps-xhr-upload-service.js +2 -1
- package/package.json +2 -2
|
@@ -6,7 +6,7 @@ const ps_design_system_1 = require("@pallasoft/ps-design-system");
|
|
|
6
6
|
const ps_icons_1 = require("@pallasoft/ps-icons");
|
|
7
7
|
const ps_file_icon_button_classes_1 = require("../constants/ps-file-icon-button-classes");
|
|
8
8
|
const PsFileIconButton = ({ disabled = false, download, href, iconKey, label, onClick, tone = 'neutral', }) => {
|
|
9
|
-
const className = ps_design_system_1.PallasoftClassNameService.merge('ps-focus-ring ps-control-square ps-control-compact inline-flex shrink-0 items-center justify-center rounded-ps-control text-
|
|
9
|
+
const className = ps_design_system_1.PallasoftClassNameService.merge('ps-focus-ring ps-control-square ps-control-compact inline-flex shrink-0 items-center justify-center rounded-ps-control text-muted transition disabled:pointer-events-none disabled:opacity-40', ps_file_icon_button_classes_1.PsFileIconButtonClasses[tone]);
|
|
10
10
|
const icon = ((0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { "aria-hidden": 'true', className: 'size-ps-control-icon-standalone', iconKey: iconKey }));
|
|
11
11
|
return href === undefined ? ((0, jsx_runtime_1.jsx)("button", { "aria-label": label, className: className, disabled: disabled, onClick: onClick, title: label, type: 'button', children: icon })) : ((0, jsx_runtime_1.jsx)("a", { "aria-label": label, className: className, download: download, href: href, title: label, children: icon }));
|
|
12
12
|
};
|
|
@@ -21,7 +21,7 @@ const PsFileList = ({ busyIds = [], files, formatDate, labels, onDelete, onOpen,
|
|
|
21
21
|
? null
|
|
22
22
|
: formatDate(file.createdAt),
|
|
23
23
|
].filter((value) => value !== null);
|
|
24
|
-
return ((0, jsx_runtime_1.jsxs)("li", { className: 'group flex min-w-0 items-center gap-3 rounded-ps-control border border-line bg-surface p-2 transition hover:border-primary/40', children: [(0, jsx_runtime_1.jsxs)("button", { "aria-label": `${text.open} ${file.name}`, className: 'ps-focus-ring flex min-w-0 flex-1 items-center gap-3 rounded-ps-control text-left', onClick: () => onOpen(index), type: 'button', children: [isImage ? ((0, jsx_runtime_1.jsx)("img", { alt: '', className: 'h-12 w-12 shrink-0 rounded-ps-control border border-line object-cover', loading: 'lazy', src: file.url })) : ((0, jsx_runtime_1.jsx)(ps_file_kind_icon_1.PsFileKindIcon, { className: 'h-12 w-12', contentType: file.contentType, name: file.name })), (0, jsx_runtime_1.jsxs)("span", { className: 'flex min-w-0 flex-col', children: [(0, jsx_runtime_1.jsx)("span", { className: 'truncate text-sm font-medium text-ink group-hover:text-primary', children: file.name }), meta.length > 0 ? ((0, jsx_runtime_1.jsx)("span", { className: 'truncate text-xs text-
|
|
24
|
+
return ((0, jsx_runtime_1.jsxs)("li", { className: 'group flex min-w-0 items-center gap-3 rounded-ps-control border border-line bg-surface p-2 transition hover:border-primary/40', children: [(0, jsx_runtime_1.jsxs)("button", { "aria-label": `${text.open} ${file.name}`, className: 'ps-focus-ring flex min-w-0 flex-1 items-center gap-3 rounded-ps-control text-left', onClick: () => onOpen(index), type: 'button', children: [isImage ? ((0, jsx_runtime_1.jsx)("img", { alt: '', className: 'h-12 w-12 shrink-0 rounded-ps-control border border-line object-cover', loading: 'lazy', src: file.url })) : ((0, jsx_runtime_1.jsx)(ps_file_kind_icon_1.PsFileKindIcon, { className: 'h-12 w-12', contentType: file.contentType, name: file.name })), (0, jsx_runtime_1.jsxs)("span", { className: 'flex min-w-0 flex-col', children: [(0, jsx_runtime_1.jsx)("span", { className: 'truncate text-sm font-medium text-ink group-hover:text-primary', children: file.name }), meta.length > 0 ? ((0, jsx_runtime_1.jsx)("span", { className: 'truncate text-xs text-muted', children: meta.join(' · ') })) : null] })] }), (0, jsx_runtime_1.jsxs)("div", { className: 'flex shrink-0 items-center gap-0.5', children: [(0, jsx_runtime_1.jsx)(ps_file_icon_button_1.PsFileIconButton, { download: file.name, href: file.downloadUrl === undefined ? file.url : file.downloadUrl, iconKey: ps_icons_1.PsIconKey.Download, label: `${text.download} ${file.name}` }), onRename ? ((0, jsx_runtime_1.jsx)(ps_file_icon_button_1.PsFileIconButton, { disabled: busyIds.includes(file.id), iconKey: ps_icons_1.PsIconKey.Pencil, label: `${text.rename} ${file.name}`, onClick: () => onRename(file) })) : null, onDelete ? ((0, jsx_runtime_1.jsx)(ps_file_icon_button_1.PsFileIconButton, { disabled: busyIds.includes(file.id), iconKey: ps_icons_1.PsIconKey.Trash, label: `${text.delete} ${file.name}`, onClick: () => onDelete(file), tone: 'danger' })) : null] })] }, file.id));
|
|
25
25
|
}) }));
|
|
26
26
|
};
|
|
27
27
|
exports.PsFileList = PsFileList;
|
|
@@ -21,6 +21,7 @@ const PsFilePicker = ({ accept, acceptLabel, className, disabled = false, dropLa
|
|
|
21
21
|
const rowLabels = { ...ps_upload_labels_1.PsUploadLabels, ...uploadLabels };
|
|
22
22
|
const details = [acceptLabel, maxSizeLabel].filter((value) => value !== undefined && value !== '');
|
|
23
23
|
const chooseLabel = multiple ? text.choose : text.chooseOne;
|
|
24
|
+
const dragHint = multiple ? text.dragHint : text.dragHintOne;
|
|
24
25
|
const scanLabel = scan === undefined ? undefined : text.scan;
|
|
25
26
|
if (isLoading)
|
|
26
27
|
return ((0, jsx_runtime_1.jsx)("span", { "aria-busy": 'true', className: ps_design_system_1.PallasoftClassNameService.merge('ps-skeleton block min-h-48 w-full rounded-ps-control', className), role: 'status' }));
|
|
@@ -67,6 +68,6 @@ const PsFilePicker = ({ accept, acceptLabel, className, disabled = false, dropLa
|
|
|
67
68
|
select(event.dataTransfer.files);
|
|
68
69
|
}, children: [(0, jsx_runtime_1.jsx)("span", { "aria-hidden": 'true', className: ps_design_system_1.PallasoftClassNameService.merge('flex size-12 items-center justify-center rounded-full transition-colors duration-200', isDragging
|
|
69
70
|
? 'bg-primary text-[color:var(--ps-color-primary-contrast)]'
|
|
70
|
-
: 'bg-primary-soft text-primary'), children: (0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { className: 'size-6', iconKey: ps_icons_1.PsIconKey.Upload }) }), (0, jsx_runtime_1.jsxs)("div", { className: 'flex flex-col gap-1', children: [(0, jsx_runtime_1.jsx)("p", { className: 'text-base font-semibold text-ink', children: isDragging ? (text.dropActive) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("span", { className: touchLabel === undefined ? '' : '[@media(pointer:coarse)]:hidden', children: dropLabel }), touchLabel === undefined ? null : ((0, jsx_runtime_1.jsx)("span", { className: 'hidden [@media(pointer:coarse)]:inline', children: touchLabel }))] })) }), (0, jsx_runtime_1.jsx)("p", { className: 'text-sm text-ink/60 [@media(pointer:coarse)]:hidden', children:
|
|
71
|
+
: 'bg-primary-soft text-primary'), children: (0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { className: 'size-6', iconKey: ps_icons_1.PsIconKey.Upload }) }), (0, jsx_runtime_1.jsxs)("div", { className: 'flex flex-col gap-1', children: [(0, jsx_runtime_1.jsx)("p", { className: 'text-base font-semibold text-ink', children: isDragging ? (text.dropActive) : ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("span", { className: touchLabel === undefined ? '' : '[@media(pointer:coarse)]:hidden', children: dropLabel }), touchLabel === undefined ? null : ((0, jsx_runtime_1.jsx)("span", { className: 'hidden [@media(pointer:coarse)]:inline', children: touchLabel }))] })) }), dragHint === '' ? null : ((0, jsx_runtime_1.jsx)("p", { className: 'text-sm text-ink/60 [@media(pointer:coarse)]:hidden', children: dragHint }))] }), (0, jsx_runtime_1.jsx)(ps_file_picker_actions_1.PsFilePickerActions, { chooseLabel: chooseLabel, className: 'flex [@media(pointer:coarse)]:hidden', disabled: disabled, isTouch: false, onChoose: browse, onScan: openScan, scanLabel: scanLabel }), (0, jsx_runtime_1.jsx)(ps_file_picker_actions_1.PsFilePickerActions, { chooseLabel: chooseLabel, className: 'hidden [@media(pointer:coarse)]:flex', disabled: disabled, isTouch: true, onChoose: browse, onScan: openScan, scanLabel: scanLabel }), details.length > 0 ? (0, jsx_runtime_1.jsx)("p", { className: 'text-xs text-muted', children: details.join(' · ') }) : null, (0, jsx_runtime_1.jsx)("input", { accept: acceptAttr, "aria-hidden": 'true', className: 'sr-only', disabled: disabled, multiple: multiple, onChange: onChange, onClick: (event) => event.stopPropagation(), ref: input, tabIndex: -1, type: 'file' })] }), queue === undefined || queue.items.length === 0 ? null : ((0, jsx_runtime_1.jsx)("ul", { "aria-label": rowLabels.title, className: 'flex flex-col gap-2', children: queue.items.map((item) => ((0, jsx_runtime_1.jsx)(ps_upload_row_1.PsUploadRow, { item: item, labels: rowLabels, onCancel: () => queue.cancel(item.id), onRemove: () => queue.remove(item.id), onRetry: () => queue.retry(item.id) }, item.id))) })), scan === undefined ? null : ((0, jsx_runtime_1.jsx)(ps_document_scanner_1.PsDocumentScanner, { ...scan, fileName: scanName === null ? ps_scan_config_1.PsScanConfig.defaultFileName : scanName, isOpen: scanName !== null, onClose: () => setScanName(null), onComplete: select }))] }));
|
|
71
72
|
};
|
|
72
73
|
exports.PsFilePicker = PsFilePicker;
|
|
@@ -19,6 +19,6 @@ const PsUploadRow = ({ item, labels, onCancel, onRemove, onRetry }) => {
|
|
|
19
19
|
: item.status === ps_upload_status_1.PsUploadStatus.failed && item.error
|
|
20
20
|
? item.error
|
|
21
21
|
: labels[item.status];
|
|
22
|
-
return ((0, jsx_runtime_1.jsxs)("li", { className: 'flex items-center gap-3 rounded-ps-control border border-line px-3 py-2.5', children: [(0, jsx_runtime_1.jsx)(ps_file_kind_icon_1.PsFileKindIcon, { contentType: item.file.type, name: item.file.name }), (0, jsx_runtime_1.jsxs)("div", { className: 'flex min-w-0 flex-1 flex-col gap-1.5', children: [(0, jsx_runtime_1.jsx)("p", { className: 'truncate text-sm font-medium text-ink', children: item.file.name }), (0, jsx_runtime_1.jsx)(ps_progress_bar_1.PsProgressBar, { label: item.file.name, tone: ps_upload_status_tones_1.PsUploadStatusTones[item.status], value: isProblem ? 1 : item.progress }), (0, jsx_runtime_1.jsxs)("p", { className: `truncate text-xs ${isProblem ? 'text-danger' : item.status === ps_upload_status_1.PsUploadStatus.done ? 'text-success' : 'text-
|
|
22
|
+
return ((0, jsx_runtime_1.jsxs)("li", { className: 'flex items-center gap-3 rounded-ps-control border border-line px-3 py-2.5', children: [(0, jsx_runtime_1.jsx)(ps_file_kind_icon_1.PsFileKindIcon, { contentType: item.file.type, name: item.file.name }), (0, jsx_runtime_1.jsxs)("div", { className: 'flex min-w-0 flex-1 flex-col gap-1.5', children: [(0, jsx_runtime_1.jsx)("p", { className: 'truncate text-sm font-medium text-ink', children: item.file.name }), (0, jsx_runtime_1.jsx)(ps_progress_bar_1.PsProgressBar, { label: item.file.name, tone: ps_upload_status_tones_1.PsUploadStatusTones[item.status], value: isProblem ? 1 : item.progress }), (0, jsx_runtime_1.jsxs)("p", { className: `truncate text-xs ${isProblem ? 'text-danger' : item.status === ps_upload_status_1.PsUploadStatus.done ? 'text-success' : 'text-muted'}`, role: item.status === ps_upload_status_1.PsUploadStatus.failed ? 'alert' : undefined, children: [size, " \u00B7 ", status] })] }), (0, jsx_runtime_1.jsxs)("div", { className: 'flex w-20 shrink-0 items-center justify-end gap-1', children: [isProblem ? ((0, jsx_runtime_1.jsx)(ps_file_icon_button_1.PsFileIconButton, { iconKey: ps_icons_1.PsIconKey.Refresh, label: `${labels.retry} ${item.file.name}`, onClick: onRetry })) : null, isActive ? ((0, jsx_runtime_1.jsx)(ps_file_icon_button_1.PsFileIconButton, { iconKey: ps_icons_1.PsIconKey.Close, label: `${labels.cancel} ${item.file.name}`, onClick: onCancel, tone: 'danger' })) : item.status === ps_upload_status_1.PsUploadStatus.done ? ((0, jsx_runtime_1.jsx)("span", { className: 'ps-control-square ps-control-compact inline-flex items-center justify-center text-success', children: (0, jsx_runtime_1.jsx)(ps_icons_1.PsIcon, { "aria-label": labels.done, className: 'h-4 w-4', iconKey: ps_icons_1.PsIconKey.Check }) })) : ((0, jsx_runtime_1.jsx)(ps_file_icon_button_1.PsFileIconButton, { iconKey: ps_icons_1.PsIconKey.Close, label: `${labels.remove} ${item.file.name}`, onClick: onRemove }))] })] }));
|
|
23
23
|
};
|
|
24
24
|
exports.PsUploadRow = PsUploadRow;
|
|
@@ -3,7 +3,7 @@ import { PallasoftClassNameService } from '@pallasoft/ps-design-system';
|
|
|
3
3
|
import { PsIcon } from '@pallasoft/ps-icons';
|
|
4
4
|
import { PsFileIconButtonClasses } from '../constants/ps-file-icon-button-classes';
|
|
5
5
|
export const PsFileIconButton = ({ disabled = false, download, href, iconKey, label, onClick, tone = 'neutral', }) => {
|
|
6
|
-
const className = PallasoftClassNameService.merge('ps-focus-ring ps-control-square ps-control-compact inline-flex shrink-0 items-center justify-center rounded-ps-control text-
|
|
6
|
+
const className = PallasoftClassNameService.merge('ps-focus-ring ps-control-square ps-control-compact inline-flex shrink-0 items-center justify-center rounded-ps-control text-muted transition disabled:pointer-events-none disabled:opacity-40', PsFileIconButtonClasses[tone]);
|
|
7
7
|
const icon = (_jsx(PsIcon, { "aria-hidden": 'true', className: 'size-ps-control-icon-standalone', iconKey: iconKey }));
|
|
8
8
|
return href === undefined ? (_jsx("button", { "aria-label": label, className: className, disabled: disabled, onClick: onClick, title: label, type: 'button', children: icon })) : (_jsx("a", { "aria-label": label, className: className, download: download, href: href, title: label, children: icon }));
|
|
9
9
|
};
|
|
@@ -18,6 +18,6 @@ export const PsFileList = ({ busyIds = [], files, formatDate, labels, onDelete,
|
|
|
18
18
|
? null
|
|
19
19
|
: formatDate(file.createdAt),
|
|
20
20
|
].filter((value) => value !== null);
|
|
21
|
-
return (_jsxs("li", { className: 'group flex min-w-0 items-center gap-3 rounded-ps-control border border-line bg-surface p-2 transition hover:border-primary/40', children: [_jsxs("button", { "aria-label": `${text.open} ${file.name}`, className: 'ps-focus-ring flex min-w-0 flex-1 items-center gap-3 rounded-ps-control text-left', onClick: () => onOpen(index), type: 'button', children: [isImage ? (_jsx("img", { alt: '', className: 'h-12 w-12 shrink-0 rounded-ps-control border border-line object-cover', loading: 'lazy', src: file.url })) : (_jsx(PsFileKindIcon, { className: 'h-12 w-12', contentType: file.contentType, name: file.name })), _jsxs("span", { className: 'flex min-w-0 flex-col', children: [_jsx("span", { className: 'truncate text-sm font-medium text-ink group-hover:text-primary', children: file.name }), meta.length > 0 ? (_jsx("span", { className: 'truncate text-xs text-
|
|
21
|
+
return (_jsxs("li", { className: 'group flex min-w-0 items-center gap-3 rounded-ps-control border border-line bg-surface p-2 transition hover:border-primary/40', children: [_jsxs("button", { "aria-label": `${text.open} ${file.name}`, className: 'ps-focus-ring flex min-w-0 flex-1 items-center gap-3 rounded-ps-control text-left', onClick: () => onOpen(index), type: 'button', children: [isImage ? (_jsx("img", { alt: '', className: 'h-12 w-12 shrink-0 rounded-ps-control border border-line object-cover', loading: 'lazy', src: file.url })) : (_jsx(PsFileKindIcon, { className: 'h-12 w-12', contentType: file.contentType, name: file.name })), _jsxs("span", { className: 'flex min-w-0 flex-col', children: [_jsx("span", { className: 'truncate text-sm font-medium text-ink group-hover:text-primary', children: file.name }), meta.length > 0 ? (_jsx("span", { className: 'truncate text-xs text-muted', children: meta.join(' · ') })) : null] })] }), _jsxs("div", { className: 'flex shrink-0 items-center gap-0.5', children: [_jsx(PsFileIconButton, { download: file.name, href: file.downloadUrl === undefined ? file.url : file.downloadUrl, iconKey: PsIconKey.Download, label: `${text.download} ${file.name}` }), onRename ? (_jsx(PsFileIconButton, { disabled: busyIds.includes(file.id), iconKey: PsIconKey.Pencil, label: `${text.rename} ${file.name}`, onClick: () => onRename(file) })) : null, onDelete ? (_jsx(PsFileIconButton, { disabled: busyIds.includes(file.id), iconKey: PsIconKey.Trash, label: `${text.delete} ${file.name}`, onClick: () => onDelete(file), tone: 'danger' })) : null] })] }, file.id));
|
|
22
22
|
}) }));
|
|
23
23
|
};
|
|
@@ -18,6 +18,7 @@ export const PsFilePicker = ({ accept, acceptLabel, className, disabled = false,
|
|
|
18
18
|
const rowLabels = { ...PsUploadLabels, ...uploadLabels };
|
|
19
19
|
const details = [acceptLabel, maxSizeLabel].filter((value) => value !== undefined && value !== '');
|
|
20
20
|
const chooseLabel = multiple ? text.choose : text.chooseOne;
|
|
21
|
+
const dragHint = multiple ? text.dragHint : text.dragHintOne;
|
|
21
22
|
const scanLabel = scan === undefined ? undefined : text.scan;
|
|
22
23
|
if (isLoading)
|
|
23
24
|
return (_jsx("span", { "aria-busy": 'true', className: PallasoftClassNameService.merge('ps-skeleton block min-h-48 w-full rounded-ps-control', className), role: 'status' }));
|
|
@@ -64,5 +65,5 @@ export const PsFilePicker = ({ accept, acceptLabel, className, disabled = false,
|
|
|
64
65
|
select(event.dataTransfer.files);
|
|
65
66
|
}, children: [_jsx("span", { "aria-hidden": 'true', className: PallasoftClassNameService.merge('flex size-12 items-center justify-center rounded-full transition-colors duration-200', isDragging
|
|
66
67
|
? 'bg-primary text-[color:var(--ps-color-primary-contrast)]'
|
|
67
|
-
: 'bg-primary-soft text-primary'), children: _jsx(PsIcon, { className: 'size-6', iconKey: PsIconKey.Upload }) }), _jsxs("div", { className: 'flex flex-col gap-1', children: [_jsx("p", { className: 'text-base font-semibold text-ink', children: isDragging ? (text.dropActive) : (_jsxs(_Fragment, { children: [_jsx("span", { className: touchLabel === undefined ? '' : '[@media(pointer:coarse)]:hidden', children: dropLabel }), touchLabel === undefined ? null : (_jsx("span", { className: 'hidden [@media(pointer:coarse)]:inline', children: touchLabel }))] })) }), _jsx("p", { className: 'text-sm text-ink/60 [@media(pointer:coarse)]:hidden', children:
|
|
68
|
+
: 'bg-primary-soft text-primary'), children: _jsx(PsIcon, { className: 'size-6', iconKey: PsIconKey.Upload }) }), _jsxs("div", { className: 'flex flex-col gap-1', children: [_jsx("p", { className: 'text-base font-semibold text-ink', children: isDragging ? (text.dropActive) : (_jsxs(_Fragment, { children: [_jsx("span", { className: touchLabel === undefined ? '' : '[@media(pointer:coarse)]:hidden', children: dropLabel }), touchLabel === undefined ? null : (_jsx("span", { className: 'hidden [@media(pointer:coarse)]:inline', children: touchLabel }))] })) }), dragHint === '' ? null : (_jsx("p", { className: 'text-sm text-ink/60 [@media(pointer:coarse)]:hidden', children: dragHint }))] }), _jsx(PsFilePickerActions, { chooseLabel: chooseLabel, className: 'flex [@media(pointer:coarse)]:hidden', disabled: disabled, isTouch: false, onChoose: browse, onScan: openScan, scanLabel: scanLabel }), _jsx(PsFilePickerActions, { chooseLabel: chooseLabel, className: 'hidden [@media(pointer:coarse)]:flex', disabled: disabled, isTouch: true, onChoose: browse, onScan: openScan, scanLabel: scanLabel }), details.length > 0 ? _jsx("p", { className: 'text-xs text-muted', children: details.join(' · ') }) : null, _jsx("input", { accept: acceptAttr, "aria-hidden": 'true', className: 'sr-only', disabled: disabled, multiple: multiple, onChange: onChange, onClick: (event) => event.stopPropagation(), ref: input, tabIndex: -1, type: 'file' })] }), queue === undefined || queue.items.length === 0 ? null : (_jsx("ul", { "aria-label": rowLabels.title, className: 'flex flex-col gap-2', children: queue.items.map((item) => (_jsx(PsUploadRow, { item: item, labels: rowLabels, onCancel: () => queue.cancel(item.id), onRemove: () => queue.remove(item.id), onRetry: () => queue.retry(item.id) }, item.id))) })), scan === undefined ? null : (_jsx(PsDocumentScanner, { ...scan, fileName: scanName === null ? PsScanConfig.defaultFileName : scanName, isOpen: scanName !== null, onClose: () => setScanName(null), onComplete: select }))] }));
|
|
68
69
|
};
|
|
@@ -16,5 +16,5 @@ export const PsUploadRow = ({ item, labels, onCancel, onRemove, onRetry }) => {
|
|
|
16
16
|
: item.status === PsUploadStatus.failed && item.error
|
|
17
17
|
? item.error
|
|
18
18
|
: labels[item.status];
|
|
19
|
-
return (_jsxs("li", { className: 'flex items-center gap-3 rounded-ps-control border border-line px-3 py-2.5', children: [_jsx(PsFileKindIcon, { contentType: item.file.type, name: item.file.name }), _jsxs("div", { className: 'flex min-w-0 flex-1 flex-col gap-1.5', children: [_jsx("p", { className: 'truncate text-sm font-medium text-ink', children: item.file.name }), _jsx(PsProgressBar, { label: item.file.name, tone: PsUploadStatusTones[item.status], value: isProblem ? 1 : item.progress }), _jsxs("p", { className: `truncate text-xs ${isProblem ? 'text-danger' : item.status === PsUploadStatus.done ? 'text-success' : 'text-
|
|
19
|
+
return (_jsxs("li", { className: 'flex items-center gap-3 rounded-ps-control border border-line px-3 py-2.5', children: [_jsx(PsFileKindIcon, { contentType: item.file.type, name: item.file.name }), _jsxs("div", { className: 'flex min-w-0 flex-1 flex-col gap-1.5', children: [_jsx("p", { className: 'truncate text-sm font-medium text-ink', children: item.file.name }), _jsx(PsProgressBar, { label: item.file.name, tone: PsUploadStatusTones[item.status], value: isProblem ? 1 : item.progress }), _jsxs("p", { className: `truncate text-xs ${isProblem ? 'text-danger' : item.status === PsUploadStatus.done ? 'text-success' : 'text-muted'}`, role: item.status === PsUploadStatus.failed ? 'alert' : undefined, children: [size, " \u00B7 ", status] })] }), _jsxs("div", { className: 'flex w-20 shrink-0 items-center justify-end gap-1', children: [isProblem ? (_jsx(PsFileIconButton, { iconKey: PsIconKey.Refresh, label: `${labels.retry} ${item.file.name}`, onClick: onRetry })) : null, isActive ? (_jsx(PsFileIconButton, { iconKey: PsIconKey.Close, label: `${labels.cancel} ${item.file.name}`, onClick: onCancel, tone: 'danger' })) : item.status === PsUploadStatus.done ? (_jsx("span", { className: 'ps-control-square ps-control-compact inline-flex items-center justify-center text-success', children: _jsx(PsIcon, { "aria-label": labels.done, className: 'h-4 w-4', iconKey: PsIconKey.Check }) })) : (_jsx(PsFileIconButton, { iconKey: PsIconKey.Close, label: `${labels.remove} ${item.file.name}`, onClick: onRemove }))] })] }));
|
|
20
20
|
};
|
|
@@ -1,28 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Common } from '@pallasoft/ps-utilities';
|
|
2
2
|
export class PsImageTextService {
|
|
3
3
|
static matches(layer, query) {
|
|
4
|
-
|
|
5
|
-
return [];
|
|
6
|
-
const items = layer.words.map((word, index) => ({
|
|
7
|
-
isBreakAfter: index < layer.words.length - 1,
|
|
8
|
-
text: word.text,
|
|
9
|
-
}));
|
|
10
|
-
const rects = [];
|
|
11
|
-
PsTextSearchService.findInItems(items, query).forEach((match, matchIndex) => {
|
|
12
|
-
match.parts.forEach((part) => {
|
|
13
|
-
const word = layer.words[part.itemIndex];
|
|
14
|
-
const length = word.text.length;
|
|
15
|
-
const left = word.box.left + (word.box.width * part.start) / length;
|
|
16
|
-
const width = (word.box.width * (part.end - part.start)) / length;
|
|
17
|
-
rects.push({
|
|
18
|
-
height: word.box.height / layer.height,
|
|
19
|
-
left: left / layer.width,
|
|
20
|
-
matchIndex,
|
|
21
|
-
top: word.box.top / layer.height,
|
|
22
|
-
width: width / layer.width,
|
|
23
|
-
});
|
|
24
|
-
});
|
|
25
|
-
});
|
|
26
|
-
return rects;
|
|
4
|
+
return Common.TextLayerService.fractionRects(layer, Common.TextLayerService.phraseMatches(layer, query)).map((rect) => ({ ...rect.box, matchIndex: rect.matchIndex }));
|
|
27
5
|
}
|
|
28
6
|
}
|
|
@@ -1,86 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
const marks = /\p{M}/gu;
|
|
1
|
+
import { Common } from '@pallasoft/ps-utilities';
|
|
3
2
|
export class PsTextSearchService {
|
|
4
3
|
static normalize(text) {
|
|
5
|
-
|
|
6
|
-
const ends = [];
|
|
7
|
-
let folded = '';
|
|
8
|
-
let isAfterSpace = false;
|
|
9
|
-
let index = 0;
|
|
10
|
-
while (index < text.length) {
|
|
11
|
-
const char = String.fromCodePoint(text.codePointAt(index));
|
|
12
|
-
const next = index + char.length;
|
|
13
|
-
if (whitespace.test(char)) {
|
|
14
|
-
if (!isAfterSpace) {
|
|
15
|
-
folded += ' ';
|
|
16
|
-
starts.push(index);
|
|
17
|
-
ends.push(next);
|
|
18
|
-
}
|
|
19
|
-
isAfterSpace = true;
|
|
20
|
-
}
|
|
21
|
-
else {
|
|
22
|
-
const plain = char.toLowerCase().normalize('NFD').replace(marks, '');
|
|
23
|
-
for (let at = 0; at < plain.length; at += 1) {
|
|
24
|
-
folded += plain[at];
|
|
25
|
-
starts.push(index);
|
|
26
|
-
ends.push(next);
|
|
27
|
-
}
|
|
28
|
-
isAfterSpace = false;
|
|
29
|
-
}
|
|
30
|
-
index = next;
|
|
31
|
-
}
|
|
32
|
-
return { ends, starts, text: folded };
|
|
4
|
+
return Common.TextSearchService.normalize(text);
|
|
33
5
|
}
|
|
34
6
|
static find(text, query) {
|
|
35
|
-
|
|
36
|
-
if (needle.length === 0)
|
|
37
|
-
return [];
|
|
38
|
-
const haystack = PsTextSearchService.normalize(text);
|
|
39
|
-
const matches = [];
|
|
40
|
-
let from = haystack.text.indexOf(needle);
|
|
41
|
-
while (from !== -1) {
|
|
42
|
-
matches.push({
|
|
43
|
-
end: haystack.ends[from + needle.length - 1],
|
|
44
|
-
start: haystack.starts[from],
|
|
45
|
-
});
|
|
46
|
-
from = haystack.text.indexOf(needle, from + needle.length);
|
|
47
|
-
}
|
|
48
|
-
return matches;
|
|
7
|
+
return Common.TextSearchService.find(text, query);
|
|
49
8
|
}
|
|
50
9
|
static findInItems(items, query) {
|
|
51
|
-
|
|
52
|
-
let joined = '';
|
|
53
|
-
items.forEach((item) => {
|
|
54
|
-
offsets.push(joined.length);
|
|
55
|
-
joined += item.isBreakAfter ? `${item.text} ` : item.text;
|
|
56
|
-
});
|
|
57
|
-
return PsTextSearchService.find(joined, query).map((match) => {
|
|
58
|
-
const parts = [];
|
|
59
|
-
items.forEach((item, itemIndex) => {
|
|
60
|
-
const start = Math.max(match.start, offsets[itemIndex]) - offsets[itemIndex];
|
|
61
|
-
const end = Math.min(match.end, offsets[itemIndex] + item.text.length) - offsets[itemIndex];
|
|
62
|
-
if (end > start)
|
|
63
|
-
parts.push({ end, itemIndex, start });
|
|
64
|
-
});
|
|
65
|
-
return { parts };
|
|
66
|
-
});
|
|
10
|
+
return Common.TextSearchService.findInItems(items, query);
|
|
67
11
|
}
|
|
68
12
|
static segments(text, matches, firstIndex = 0) {
|
|
69
|
-
|
|
70
|
-
let cursor = 0;
|
|
71
|
-
matches.forEach((match, index) => {
|
|
72
|
-
if (match.start > cursor)
|
|
73
|
-
segments.push({ isMatch: false, matchIndex: null, text: text.slice(cursor, match.start) });
|
|
74
|
-
segments.push({
|
|
75
|
-
isMatch: true,
|
|
76
|
-
matchIndex: firstIndex + index,
|
|
77
|
-
text: text.slice(match.start, match.end),
|
|
78
|
-
});
|
|
79
|
-
cursor = match.end;
|
|
80
|
-
});
|
|
81
|
-
if (cursor < text.length)
|
|
82
|
-
segments.push({ isMatch: false, matchIndex: null, text: text.slice(cursor) });
|
|
83
|
-
return segments;
|
|
13
|
+
return Common.TextSearchService.segments(text, matches, firstIndex);
|
|
84
14
|
}
|
|
85
15
|
static tableSegments(rows, query) {
|
|
86
16
|
let offset = 0;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Common } from '@pallasoft/ps-utilities';
|
|
1
2
|
import { PsUploadMessages } from '../constants/ps-upload-messages';
|
|
2
3
|
export class PsXhrUploadService {
|
|
3
4
|
static parse(text) {
|
|
@@ -36,7 +37,7 @@ export class PsXhrUploadService {
|
|
|
36
37
|
if (xhr.status >= 200 && xhr.status < 300)
|
|
37
38
|
resolve({ body, contentType: xhr.getResponseHeader('content-type'), status: xhr.status });
|
|
38
39
|
else
|
|
39
|
-
reject(
|
|
40
|
+
reject(Common.ErrorResponseService.create(PsXhrUploadService.errorMessage(body), xhr.status));
|
|
40
41
|
};
|
|
41
42
|
xhr.onerror = () => reject(new Error(PsUploadMessages.failed));
|
|
42
43
|
xhr.onabort = () => reject(new Error(PsUploadMessages.cancelled));
|
|
@@ -1,6 +1,2 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
export
|
|
3
|
-
height: number;
|
|
4
|
-
width: number;
|
|
5
|
-
words: PsImageTextWord[];
|
|
6
|
-
}
|
|
1
|
+
import type { TextLayer } from '@pallasoft/ps-utilities';
|
|
2
|
+
export type PsImageTextLayer = TextLayer;
|
|
@@ -1,32 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PsImageTextService = void 0;
|
|
4
|
-
const
|
|
4
|
+
const ps_utilities_1 = require("@pallasoft/ps-utilities");
|
|
5
5
|
class PsImageTextService {
|
|
6
6
|
static matches(layer, query) {
|
|
7
|
-
|
|
8
|
-
return [];
|
|
9
|
-
const items = layer.words.map((word, index) => ({
|
|
10
|
-
isBreakAfter: index < layer.words.length - 1,
|
|
11
|
-
text: word.text,
|
|
12
|
-
}));
|
|
13
|
-
const rects = [];
|
|
14
|
-
ps_text_search_service_1.PsTextSearchService.findInItems(items, query).forEach((match, matchIndex) => {
|
|
15
|
-
match.parts.forEach((part) => {
|
|
16
|
-
const word = layer.words[part.itemIndex];
|
|
17
|
-
const length = word.text.length;
|
|
18
|
-
const left = word.box.left + (word.box.width * part.start) / length;
|
|
19
|
-
const width = (word.box.width * (part.end - part.start)) / length;
|
|
20
|
-
rects.push({
|
|
21
|
-
height: word.box.height / layer.height,
|
|
22
|
-
left: left / layer.width,
|
|
23
|
-
matchIndex,
|
|
24
|
-
top: word.box.top / layer.height,
|
|
25
|
-
width: width / layer.width,
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
return rects;
|
|
7
|
+
return ps_utilities_1.Common.TextLayerService.fractionRects(layer, ps_utilities_1.Common.TextLayerService.phraseMatches(layer, query)).map((rect) => ({ ...rect.box, matchIndex: rect.matchIndex }));
|
|
30
8
|
}
|
|
31
9
|
}
|
|
32
10
|
exports.PsImageTextService = PsImageTextService;
|
|
@@ -1,89 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PsTextSearchService = void 0;
|
|
4
|
-
const
|
|
5
|
-
const marks = /\p{M}/gu;
|
|
4
|
+
const ps_utilities_1 = require("@pallasoft/ps-utilities");
|
|
6
5
|
class PsTextSearchService {
|
|
7
6
|
static normalize(text) {
|
|
8
|
-
|
|
9
|
-
const ends = [];
|
|
10
|
-
let folded = '';
|
|
11
|
-
let isAfterSpace = false;
|
|
12
|
-
let index = 0;
|
|
13
|
-
while (index < text.length) {
|
|
14
|
-
const char = String.fromCodePoint(text.codePointAt(index));
|
|
15
|
-
const next = index + char.length;
|
|
16
|
-
if (whitespace.test(char)) {
|
|
17
|
-
if (!isAfterSpace) {
|
|
18
|
-
folded += ' ';
|
|
19
|
-
starts.push(index);
|
|
20
|
-
ends.push(next);
|
|
21
|
-
}
|
|
22
|
-
isAfterSpace = true;
|
|
23
|
-
}
|
|
24
|
-
else {
|
|
25
|
-
const plain = char.toLowerCase().normalize('NFD').replace(marks, '');
|
|
26
|
-
for (let at = 0; at < plain.length; at += 1) {
|
|
27
|
-
folded += plain[at];
|
|
28
|
-
starts.push(index);
|
|
29
|
-
ends.push(next);
|
|
30
|
-
}
|
|
31
|
-
isAfterSpace = false;
|
|
32
|
-
}
|
|
33
|
-
index = next;
|
|
34
|
-
}
|
|
35
|
-
return { ends, starts, text: folded };
|
|
7
|
+
return ps_utilities_1.Common.TextSearchService.normalize(text);
|
|
36
8
|
}
|
|
37
9
|
static find(text, query) {
|
|
38
|
-
|
|
39
|
-
if (needle.length === 0)
|
|
40
|
-
return [];
|
|
41
|
-
const haystack = PsTextSearchService.normalize(text);
|
|
42
|
-
const matches = [];
|
|
43
|
-
let from = haystack.text.indexOf(needle);
|
|
44
|
-
while (from !== -1) {
|
|
45
|
-
matches.push({
|
|
46
|
-
end: haystack.ends[from + needle.length - 1],
|
|
47
|
-
start: haystack.starts[from],
|
|
48
|
-
});
|
|
49
|
-
from = haystack.text.indexOf(needle, from + needle.length);
|
|
50
|
-
}
|
|
51
|
-
return matches;
|
|
10
|
+
return ps_utilities_1.Common.TextSearchService.find(text, query);
|
|
52
11
|
}
|
|
53
12
|
static findInItems(items, query) {
|
|
54
|
-
|
|
55
|
-
let joined = '';
|
|
56
|
-
items.forEach((item) => {
|
|
57
|
-
offsets.push(joined.length);
|
|
58
|
-
joined += item.isBreakAfter ? `${item.text} ` : item.text;
|
|
59
|
-
});
|
|
60
|
-
return PsTextSearchService.find(joined, query).map((match) => {
|
|
61
|
-
const parts = [];
|
|
62
|
-
items.forEach((item, itemIndex) => {
|
|
63
|
-
const start = Math.max(match.start, offsets[itemIndex]) - offsets[itemIndex];
|
|
64
|
-
const end = Math.min(match.end, offsets[itemIndex] + item.text.length) - offsets[itemIndex];
|
|
65
|
-
if (end > start)
|
|
66
|
-
parts.push({ end, itemIndex, start });
|
|
67
|
-
});
|
|
68
|
-
return { parts };
|
|
69
|
-
});
|
|
13
|
+
return ps_utilities_1.Common.TextSearchService.findInItems(items, query);
|
|
70
14
|
}
|
|
71
15
|
static segments(text, matches, firstIndex = 0) {
|
|
72
|
-
|
|
73
|
-
let cursor = 0;
|
|
74
|
-
matches.forEach((match, index) => {
|
|
75
|
-
if (match.start > cursor)
|
|
76
|
-
segments.push({ isMatch: false, matchIndex: null, text: text.slice(cursor, match.start) });
|
|
77
|
-
segments.push({
|
|
78
|
-
isMatch: true,
|
|
79
|
-
matchIndex: firstIndex + index,
|
|
80
|
-
text: text.slice(match.start, match.end),
|
|
81
|
-
});
|
|
82
|
-
cursor = match.end;
|
|
83
|
-
});
|
|
84
|
-
if (cursor < text.length)
|
|
85
|
-
segments.push({ isMatch: false, matchIndex: null, text: text.slice(cursor) });
|
|
86
|
-
return segments;
|
|
16
|
+
return ps_utilities_1.Common.TextSearchService.segments(text, matches, firstIndex);
|
|
87
17
|
}
|
|
88
18
|
static tableSegments(rows, query) {
|
|
89
19
|
let offset = 0;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PsXhrUploadService = void 0;
|
|
4
|
+
const ps_utilities_1 = require("@pallasoft/ps-utilities");
|
|
4
5
|
const ps_upload_messages_1 = require("../constants/ps-upload-messages");
|
|
5
6
|
class PsXhrUploadService {
|
|
6
7
|
static parse(text) {
|
|
@@ -39,7 +40,7 @@ class PsXhrUploadService {
|
|
|
39
40
|
if (xhr.status >= 200 && xhr.status < 300)
|
|
40
41
|
resolve({ body, contentType: xhr.getResponseHeader('content-type'), status: xhr.status });
|
|
41
42
|
else
|
|
42
|
-
reject(
|
|
43
|
+
reject(ps_utilities_1.Common.ErrorResponseService.create(PsXhrUploadService.errorMessage(body), xhr.status));
|
|
43
44
|
};
|
|
44
45
|
xhr.onerror = () => reject(new Error(ps_upload_messages_1.PsUploadMessages.failed));
|
|
45
46
|
xhr.onabort = () => reject(new Error(ps_upload_messages_1.PsUploadMessages.cancelled));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pallasoft/ps-file-components",
|
|
3
|
-
"version": "2.4.
|
|
3
|
+
"version": "2.4.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"main": "./dist/index.js",
|
|
6
6
|
"module": "./dist/esm/index.js",
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
"@pallasoft/ps-core-components": "^2.37.0",
|
|
34
34
|
"@pallasoft/ps-icons": "^1.9.0",
|
|
35
35
|
"@pallasoft/ps-popovers": "^1.13.0",
|
|
36
|
-
"@pallasoft/ps-utilities": "^2.
|
|
36
|
+
"@pallasoft/ps-utilities": "^2.30.0",
|
|
37
37
|
"dompurify": "^3.4.17",
|
|
38
38
|
"mammoth": "^1.13.0",
|
|
39
39
|
"pdfjs-dist": "^6.3.289",
|