@pallasoft/ps-file-components 2.3.0 → 2.4.1

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 (162) hide show
  1. package/dist/components/ps-file-icon-button.js +1 -1
  2. package/dist/components/ps-file-list.js +1 -1
  3. package/dist/components/ps-file-picker.js +1 -1
  4. package/dist/components/ps-file-search-bar.d.ts +10 -0
  5. package/dist/components/ps-file-search-bar.js +25 -0
  6. package/dist/components/ps-file-viewer-content.js +9 -0
  7. package/dist/components/ps-file-viewer-pane.d.ts +1 -1
  8. package/dist/components/ps-file-viewer-pane.js +26 -2
  9. package/dist/components/ps-file-viewer.js +11 -23
  10. package/dist/components/ps-html-document.d.ts +8 -0
  11. package/dist/components/ps-html-document.js +23 -0
  12. package/dist/components/ps-html-viewer.d.ts +2 -0
  13. package/dist/components/ps-html-viewer.js +17 -0
  14. package/dist/components/ps-image-text-highlights.d.ts +9 -0
  15. package/dist/components/ps-image-text-highlights.js +31 -0
  16. package/dist/components/ps-image-viewer.d.ts +1 -1
  17. package/dist/components/ps-image-viewer.js +11 -2
  18. package/dist/components/ps-pdf-page.js +1 -1
  19. package/dist/components/ps-pdf-viewer.js +6 -2
  20. package/dist/components/ps-sheet-viewer.d.ts +2 -0
  21. package/dist/components/ps-sheet-viewer.js +26 -0
  22. package/dist/components/ps-table-view.d.ts +7 -0
  23. package/dist/components/ps-table-view.js +17 -0
  24. package/dist/components/ps-text-viewer.js +7 -14
  25. package/dist/components/ps-upload-row.js +1 -1
  26. package/dist/components/ps-word-viewer.d.ts +2 -0
  27. package/dist/components/ps-word-viewer.js +17 -0
  28. package/dist/constants/ps-file-kind-icons.js +3 -0
  29. package/dist/constants/ps-file-kind.d.ts +3 -0
  30. package/dist/constants/ps-file-kind.js +3 -0
  31. package/dist/constants/ps-file-type-config.d.ts +6 -1
  32. package/dist/constants/ps-file-type-config.js +16 -2
  33. package/dist/constants/ps-file-viewer-config.d.ts +1 -0
  34. package/dist/constants/ps-file-viewer-config.js +1 -0
  35. package/dist/constants/ps-file-viewer-kinds.d.ts +2 -2
  36. package/dist/constants/ps-file-viewer-kinds.js +17 -2
  37. package/dist/constants/ps-file-viewer-labels.d.ts +3 -0
  38. package/dist/constants/ps-file-viewer-labels.js +3 -0
  39. package/dist/constants/ps-html-sanitize-config.d.ts +8 -0
  40. package/dist/constants/ps-html-sanitize-config.js +26 -0
  41. package/dist/esm/components/ps-file-icon-button.js +1 -1
  42. package/dist/esm/components/ps-file-list.js +1 -1
  43. package/dist/esm/components/ps-file-picker.js +1 -1
  44. package/dist/esm/components/ps-file-search-bar.js +21 -0
  45. package/dist/esm/components/ps-file-viewer-content.js +9 -0
  46. package/dist/esm/components/ps-file-viewer-pane.js +27 -3
  47. package/dist/esm/components/ps-file-viewer.js +13 -25
  48. package/dist/esm/components/ps-html-document.js +19 -0
  49. package/dist/esm/components/ps-html-viewer.js +13 -0
  50. package/dist/esm/components/ps-image-text-highlights.js +27 -0
  51. package/dist/esm/components/ps-image-viewer.js +13 -4
  52. package/dist/esm/components/ps-pdf-page.js +1 -1
  53. package/dist/esm/components/ps-pdf-viewer.js +6 -2
  54. package/dist/esm/components/ps-sheet-viewer.js +22 -0
  55. package/dist/esm/components/ps-table-view.js +13 -0
  56. package/dist/esm/components/ps-text-viewer.js +7 -14
  57. package/dist/esm/components/ps-upload-row.js +1 -1
  58. package/dist/esm/components/ps-word-viewer.js +13 -0
  59. package/dist/esm/constants/ps-file-kind-icons.js +3 -0
  60. package/dist/esm/constants/ps-file-kind.js +3 -0
  61. package/dist/esm/constants/ps-file-type-config.js +16 -2
  62. package/dist/esm/constants/ps-file-viewer-config.js +1 -0
  63. package/dist/esm/constants/ps-file-viewer-kinds.js +17 -2
  64. package/dist/esm/constants/ps-file-viewer-labels.js +3 -0
  65. package/dist/esm/constants/ps-html-sanitize-config.js +23 -0
  66. package/dist/esm/hooks/use-ps-file-search.js +37 -0
  67. package/dist/esm/hooks/use-ps-file-text.js +4 -19
  68. package/dist/esm/hooks/use-ps-find-shortcut.js +23 -0
  69. package/dist/esm/hooks/use-ps-loaded-file.js +19 -0
  70. package/dist/esm/index.js +33 -0
  71. package/dist/esm/models/ps-file-search-state.js +1 -0
  72. package/dist/esm/models/ps-html-highlight-result.js +1 -0
  73. package/dist/esm/models/ps-html-text-node.js +1 -0
  74. package/dist/esm/models/ps-image-match.js +1 -0
  75. package/dist/esm/models/ps-image-text-box.js +1 -0
  76. package/dist/esm/models/ps-image-text-layer.js +1 -0
  77. package/dist/esm/models/ps-image-text-word.js +1 -0
  78. package/dist/esm/models/ps-item-match-part.js +1 -0
  79. package/dist/esm/models/ps-item-match.js +1 -0
  80. package/dist/esm/models/ps-loaded-file-state.js +1 -0
  81. package/dist/esm/models/ps-normalized-text.js +1 -0
  82. package/dist/esm/models/ps-pdf-text-item.js +1 -0
  83. package/dist/esm/models/ps-pdf-viewport-like.js +1 -0
  84. package/dist/esm/models/ps-search-item.js +1 -0
  85. package/dist/esm/models/ps-sheet-data.js +1 -0
  86. package/dist/esm/services/ps-file-fetch-service.js +14 -0
  87. package/dist/esm/services/ps-file-search-service.js +15 -0
  88. package/dist/esm/services/ps-file-type-service.js +12 -1
  89. package/dist/esm/services/ps-html-file-service.js +7 -0
  90. package/dist/esm/services/ps-html-service.js +83 -0
  91. package/dist/esm/services/ps-image-text-service.js +6 -0
  92. package/dist/esm/services/ps-label-service.js +5 -0
  93. package/dist/esm/services/ps-pdf-service.js +39 -16
  94. package/dist/esm/services/ps-sheet-service.js +23 -0
  95. package/dist/esm/services/ps-text-search-service.js +21 -26
  96. package/dist/esm/services/ps-word-service.js +15 -0
  97. package/dist/hooks/use-ps-file-search.d.ts +2 -0
  98. package/dist/hooks/use-ps-file-search.js +41 -0
  99. package/dist/hooks/use-ps-file-text.js +4 -19
  100. package/dist/hooks/use-ps-find-shortcut.d.ts +2 -0
  101. package/dist/hooks/use-ps-find-shortcut.js +27 -0
  102. package/dist/hooks/use-ps-loaded-file.d.ts +2 -0
  103. package/dist/hooks/use-ps-loaded-file.js +23 -0
  104. package/dist/index.d.ts +33 -0
  105. package/dist/index.js +33 -0
  106. package/dist/models/ps-file-search-state.d.ts +13 -0
  107. package/dist/models/ps-file-search-state.js +2 -0
  108. package/dist/models/ps-file-viewer-pane-props.d.ts +3 -1
  109. package/dist/models/ps-html-highlight-result.d.ts +4 -0
  110. package/dist/models/ps-html-highlight-result.js +2 -0
  111. package/dist/models/ps-html-text-node.d.ts +4 -0
  112. package/dist/models/ps-html-text-node.js +2 -0
  113. package/dist/models/ps-image-match.d.ts +7 -0
  114. package/dist/models/ps-image-match.js +2 -0
  115. package/dist/models/ps-image-text-box.d.ts +2 -0
  116. package/dist/models/ps-image-text-box.js +2 -0
  117. package/dist/models/ps-image-text-layer.d.ts +2 -0
  118. package/dist/models/ps-image-text-layer.js +2 -0
  119. package/dist/models/ps-image-text-word.d.ts +2 -0
  120. package/dist/models/ps-image-text-word.js +2 -0
  121. package/dist/models/ps-item-match-part.d.ts +2 -0
  122. package/dist/models/ps-item-match-part.js +2 -0
  123. package/dist/models/ps-item-match.d.ts +2 -0
  124. package/dist/models/ps-item-match.js +2 -0
  125. package/dist/models/ps-loaded-file-state.d.ts +4 -0
  126. package/dist/models/ps-loaded-file-state.js +2 -0
  127. package/dist/models/ps-normalized-text.d.ts +2 -0
  128. package/dist/models/ps-normalized-text.js +2 -0
  129. package/dist/models/ps-pdf-match.d.ts +1 -0
  130. package/dist/models/ps-pdf-text-item.d.ts +7 -0
  131. package/dist/models/ps-pdf-text-item.js +2 -0
  132. package/dist/models/ps-pdf-viewport-like.d.ts +5 -0
  133. package/dist/models/ps-pdf-viewport-like.js +2 -0
  134. package/dist/models/ps-search-item.d.ts +2 -0
  135. package/dist/models/ps-search-item.js +2 -0
  136. package/dist/models/ps-sheet-data.d.ts +4 -0
  137. package/dist/models/ps-sheet-data.js +2 -0
  138. package/dist/models/ps-text-match.d.ts +2 -4
  139. package/dist/models/ps-text-segment.d.ts +2 -5
  140. package/dist/models/ps-viewer-file.d.ts +2 -0
  141. package/dist/services/ps-file-fetch-service.d.ts +5 -0
  142. package/dist/services/ps-file-fetch-service.js +18 -0
  143. package/dist/services/ps-file-search-service.d.ts +5 -0
  144. package/dist/services/ps-file-search-service.js +19 -0
  145. package/dist/services/ps-file-type-service.js +12 -1
  146. package/dist/services/ps-html-file-service.d.ts +3 -0
  147. package/dist/services/ps-html-file-service.js +11 -0
  148. package/dist/services/ps-html-service.d.ts +7 -0
  149. package/dist/services/ps-html-service.js +120 -0
  150. package/dist/services/ps-image-text-service.d.ts +5 -0
  151. package/dist/services/ps-image-text-service.js +10 -0
  152. package/dist/services/ps-label-service.d.ts +3 -0
  153. package/dist/services/ps-label-service.js +9 -0
  154. package/dist/services/ps-pdf-service.d.ts +3 -0
  155. package/dist/services/ps-pdf-service.js +39 -16
  156. package/dist/services/ps-sheet-service.d.ts +5 -0
  157. package/dist/services/ps-sheet-service.js +60 -0
  158. package/dist/services/ps-text-search-service.d.ts +7 -0
  159. package/dist/services/ps-text-search-service.js +21 -26
  160. package/dist/services/ps-word-service.d.ts +3 -0
  161. package/dist/services/ps-word-service.js +52 -0
  162. package/package.json +6 -3
@@ -0,0 +1,83 @@
1
+ import { PsHtmlSanitizeConfig } from '../constants/ps-html-sanitize-config';
2
+ import { PsTextSearchService } from './ps-text-search-service';
3
+ export class PsHtmlService {
4
+ static async sanitize(html, allowImages) {
5
+ const library = await import('dompurify');
6
+ const forbidden = [...PsHtmlSanitizeConfig.forbiddenTags];
7
+ if (!allowImages)
8
+ forbidden.push(...PsHtmlSanitizeConfig.mediaTags);
9
+ const clean = library.default.sanitize(html, {
10
+ FORBID_ATTR: [...PsHtmlSanitizeConfig.forbiddenAttributes],
11
+ FORBID_TAGS: forbidden,
12
+ USE_PROFILES: { html: true },
13
+ });
14
+ return PsHtmlService.harden(clean);
15
+ }
16
+ static harden(html) {
17
+ const template = document.createElement('template');
18
+ template.innerHTML = html;
19
+ template.content.querySelectorAll('a').forEach((anchor) => {
20
+ anchor.setAttribute('target', PsHtmlSanitizeConfig.anchorTarget);
21
+ anchor.setAttribute('rel', PsHtmlSanitizeConfig.anchorRel);
22
+ });
23
+ template.content.querySelectorAll('img').forEach((image) => {
24
+ const source = image.getAttribute('src');
25
+ if (source === null || !source.startsWith('data:'))
26
+ image.remove();
27
+ });
28
+ return template.innerHTML;
29
+ }
30
+ static highlight(html, query) {
31
+ if (query.trim().length === 0)
32
+ return { count: 0, html };
33
+ const template = document.createElement('template');
34
+ template.innerHTML = html;
35
+ const nodes = [];
36
+ const walker = document.createTreeWalker(template.content, NodeFilter.SHOW_TEXT);
37
+ let full = '';
38
+ let previousBlock = null;
39
+ let current = walker.nextNode();
40
+ while (current !== null) {
41
+ const node = current;
42
+ const block = node.parentElement === null
43
+ ? null
44
+ : node.parentElement.closest(PsHtmlSanitizeConfig.blockSelector);
45
+ if (nodes.length > 0 && block !== previousBlock)
46
+ full += '\n';
47
+ nodes.push({ node, offset: full.length });
48
+ full += node.data;
49
+ previousBlock = block;
50
+ current = walker.nextNode();
51
+ }
52
+ const matches = PsTextSearchService.find(full, query);
53
+ if (matches.length === 0)
54
+ return { count: 0, html };
55
+ nodes.forEach(({ node, offset }) => PsHtmlService.wrap(node, offset, matches));
56
+ return { count: matches.length, html: template.innerHTML };
57
+ }
58
+ static wrap(node, offset, matches) {
59
+ const end = offset + node.data.length;
60
+ const fragment = document.createDocumentFragment();
61
+ let cursor = 0;
62
+ let hasMark = false;
63
+ matches.forEach((match, matchIndex) => {
64
+ const start = Math.max(match.start, offset) - offset;
65
+ const stop = Math.min(match.end, end) - offset;
66
+ if (stop <= start || match.start >= end || match.end <= offset)
67
+ return;
68
+ if (start > cursor)
69
+ fragment.append(node.data.slice(cursor, start));
70
+ const mark = document.createElement('mark');
71
+ mark.setAttribute('data-ps-match', String(matchIndex));
72
+ mark.textContent = node.data.slice(start, stop);
73
+ fragment.append(mark);
74
+ cursor = stop;
75
+ hasMark = true;
76
+ });
77
+ if (!hasMark)
78
+ return;
79
+ if (cursor < node.data.length)
80
+ fragment.append(node.data.slice(cursor));
81
+ node.replaceWith(fragment);
82
+ }
83
+ }
@@ -0,0 +1,6 @@
1
+ import { Common } from '@pallasoft/ps-utilities';
2
+ export class PsImageTextService {
3
+ static matches(layer, query) {
4
+ return Common.TextLayerService.fractionRects(layer, Common.TextLayerService.phraseMatches(layer, query)).map((rect) => ({ ...rect.box, matchIndex: rect.matchIndex }));
5
+ }
6
+ }
@@ -0,0 +1,5 @@
1
+ export class PsLabelService {
2
+ static fill(template, values) {
3
+ return Object.keys(values).reduce((text, key) => text.split(`{${key}}`).join(String(values[key])), template);
4
+ }
5
+ }
@@ -30,31 +30,54 @@ export class PsPdfService {
30
30
  task.promise.catch(() => undefined);
31
31
  return task;
32
32
  }
33
+ static pageMatches(items, viewport, query, pageNumber, firstIndex) {
34
+ const found = PsTextSearchService.findInItems(items.map((item) => ({ isBreakAfter: item.hasEOL, text: item.str })), query);
35
+ const rects = [];
36
+ found.forEach((match, offset) => {
37
+ match.parts.forEach((part) => {
38
+ const item = items[part.itemIndex];
39
+ const [x, y] = [item.transform[4], item.transform[5]];
40
+ const height = item.height > 0 ? item.height : Math.hypot(item.transform[2], item.transform[3]);
41
+ const start = x + (item.width * part.start) / item.str.length;
42
+ const end = x + (item.width * part.end) / item.str.length;
43
+ const [x1, y1] = viewport.convertToViewportPoint(start, y);
44
+ const [x2, y2] = viewport.convertToViewportPoint(end, y + height);
45
+ rects.push({
46
+ height: Math.abs(y2 - y1) / viewport.height,
47
+ left: Math.min(x1, x2) / viewport.width,
48
+ matchIndex: firstIndex + offset,
49
+ pageNumber,
50
+ top: Math.min(y1, y2) / viewport.height,
51
+ width: Math.abs(x2 - x1) / viewport.width,
52
+ });
53
+ });
54
+ });
55
+ return rects;
56
+ }
33
57
  static async search(document, query, rotation) {
34
58
  const matches = [];
59
+ let count = 0;
60
+ if (query.trim().length === 0)
61
+ return matches;
35
62
  for (let pageNumber = 1; pageNumber <= document.numPages; pageNumber += 1) {
36
63
  const page = await document.getPage(pageNumber);
37
64
  const viewport = page.getViewport({ rotation: page.rotate + rotation, scale: 1 });
38
65
  const content = await page.getTextContent();
66
+ const items = [];
39
67
  content.items.forEach((item) => {
40
- if (!('str' in item) || item.str.length === 0)
41
- return;
42
- PsTextSearchService.find(item.str, query).forEach((found) => {
43
- const [x, y] = [item.transform[4], item.transform[5]];
44
- const height = item.height > 0 ? item.height : Math.hypot(item.transform[2], item.transform[3]);
45
- const start = x + (item.width * found.start) / item.str.length;
46
- const end = x + (item.width * found.end) / item.str.length;
47
- const [x1, y1] = viewport.convertToViewportPoint(start, y);
48
- const [x2, y2] = viewport.convertToViewportPoint(end, y + height);
49
- matches.push({
50
- height: Math.abs(y2 - y1) / viewport.height,
51
- left: Math.min(x1, x2) / viewport.width,
52
- pageNumber,
53
- top: Math.min(y1, y2) / viewport.height,
54
- width: Math.abs(x2 - x1) / viewport.width,
68
+ if ('str' in item)
69
+ items.push({
70
+ hasEOL: item.hasEOL,
71
+ height: item.height,
72
+ str: item.str,
73
+ transform: item.transform,
74
+ width: item.width,
55
75
  });
56
- });
57
76
  });
77
+ const found = PsPdfService.pageMatches(items, viewport, query, pageNumber, count);
78
+ if (found.length > 0)
79
+ count = found[found.length - 1].matchIndex + 1;
80
+ matches.push(...found);
58
81
  }
59
82
  return matches;
60
83
  }
@@ -0,0 +1,23 @@
1
+ import { PsFileFetchService } from './ps-file-fetch-service';
2
+ export class PsSheetService {
3
+ static async load(url, signal) {
4
+ const [buffer, library] = await Promise.all([
5
+ PsFileFetchService.buffer(url, signal),
6
+ import('read-excel-file/browser'),
7
+ ]);
8
+ const sheets = await library.default(buffer);
9
+ return sheets.map((sheet) => ({
10
+ name: sheet.sheet,
11
+ rows: sheet.data.map((row) => row.map((cell) => PsSheetService.cellText(cell))),
12
+ }));
13
+ }
14
+ static cellText(value) {
15
+ if (typeof value === 'string')
16
+ return value;
17
+ if (typeof value === 'number' || typeof value === 'boolean')
18
+ return String(value);
19
+ if (value instanceof Date)
20
+ return Number.isNaN(value.getTime()) ? '' : value.toISOString().slice(0, 10);
21
+ return '';
22
+ }
23
+ }
@@ -1,32 +1,27 @@
1
+ import { Common } from '@pallasoft/ps-utilities';
1
2
  export class PsTextSearchService {
3
+ static normalize(text) {
4
+ return Common.TextSearchService.normalize(text);
5
+ }
2
6
  static find(text, query) {
3
- const needle = query.trim().toLowerCase();
4
- if (needle.length === 0)
5
- return [];
6
- const haystack = text.toLowerCase();
7
- const matches = [];
8
- let from = haystack.indexOf(needle);
9
- while (from !== -1) {
10
- matches.push({ end: from + needle.length, start: from });
11
- from = haystack.indexOf(needle, from + needle.length);
12
- }
13
- return matches;
7
+ return Common.TextSearchService.find(text, query);
8
+ }
9
+ static findInItems(items, query) {
10
+ return Common.TextSearchService.findInItems(items, query);
14
11
  }
15
12
  static segments(text, matches, firstIndex = 0) {
16
- const segments = [];
17
- let cursor = 0;
18
- matches.forEach((match, index) => {
19
- if (match.start > cursor)
20
- segments.push({ isMatch: false, matchIndex: null, text: text.slice(cursor, match.start) });
21
- segments.push({
22
- isMatch: true,
23
- matchIndex: firstIndex + index,
24
- text: text.slice(match.start, match.end),
25
- });
26
- cursor = match.end;
27
- });
28
- if (cursor < text.length)
29
- segments.push({ isMatch: false, matchIndex: null, text: text.slice(cursor) });
30
- return segments;
13
+ return Common.TextSearchService.segments(text, matches, firstIndex);
14
+ }
15
+ static tableSegments(rows, query) {
16
+ let offset = 0;
17
+ return rows.map((row) => row.map((cell) => {
18
+ const matches = PsTextSearchService.find(cell, query);
19
+ const segments = PsTextSearchService.segments(cell, matches, offset);
20
+ offset += matches.length;
21
+ return segments;
22
+ }));
23
+ }
24
+ static countSegments(table) {
25
+ return table.reduce((total, row) => total + row.reduce((sum, cell) => sum + cell.filter((part) => part.isMatch).length, 0), 0);
31
26
  }
32
27
  }
@@ -0,0 +1,15 @@
1
+ import { PsFileFetchService } from './ps-file-fetch-service';
2
+ import { PsHtmlService } from './ps-html-service';
3
+ export class PsWordService {
4
+ static async load(url, signal) {
5
+ const [buffer, library] = await Promise.all([
6
+ PsFileFetchService.buffer(url, signal),
7
+ import('mammoth/mammoth.browser'),
8
+ ]);
9
+ const convert = typeof library.convertToHtml === 'function'
10
+ ? library.convertToHtml
11
+ : library.default.convertToHtml;
12
+ const result = await convert({ arrayBuffer: buffer });
13
+ return PsHtmlService.sanitize(result.value, true);
14
+ }
15
+ }
@@ -0,0 +1,2 @@
1
+ import type { PsFileSearchState } from '../models/ps-file-search-state';
2
+ export declare const usePsFileSearch: (resetKey: string | null) => PsFileSearchState;
@@ -0,0 +1,41 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.usePsFileSearch = void 0;
4
+ const react_1 = require("react");
5
+ const ps_core_components_1 = require("@pallasoft/ps-core-components");
6
+ const ps_file_viewer_config_1 = require("../constants/ps-file-viewer-config");
7
+ const usePsFileSearch = (resetKey) => {
8
+ const [search, setSearch] = (0, react_1.useState)('');
9
+ const [activeMatch, setActiveMatch] = (0, react_1.useState)(0);
10
+ const [matchCount, setMatchCount] = (0, react_1.useState)(0);
11
+ const inputRef = (0, react_1.useRef)(null);
12
+ const query = (0, ps_core_components_1.usePsDebouncedValue)(search, ps_file_viewer_config_1.PsFileViewerConfig.searchDebounceMs);
13
+ const reset = (0, react_1.useCallback)(() => {
14
+ setSearch('');
15
+ setActiveMatch(0);
16
+ setMatchCount(0);
17
+ }, []);
18
+ (0, react_1.useEffect)(reset, [resetKey]);
19
+ (0, react_1.useEffect)(() => setActiveMatch(0), [query]);
20
+ const focus = (0, react_1.useCallback)(() => {
21
+ inputRef.current?.focus();
22
+ inputRef.current?.select();
23
+ }, []);
24
+ const step = (0, react_1.useCallback)((delta) => {
25
+ if (matchCount > 0)
26
+ setActiveMatch((current) => (current + delta + matchCount) % matchCount);
27
+ }, [matchCount]);
28
+ return {
29
+ activeMatch,
30
+ focus,
31
+ inputRef,
32
+ matchCount,
33
+ query,
34
+ reset,
35
+ search,
36
+ setMatchCount,
37
+ setSearch,
38
+ step,
39
+ };
40
+ };
41
+ exports.usePsFileSearch = usePsFileSearch;
@@ -1,25 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.usePsFileText = void 0;
4
- const react_1 = require("react");
4
+ const ps_file_fetch_service_1 = require("../services/ps-file-fetch-service");
5
+ const use_ps_loaded_file_1 = require("./use-ps-loaded-file");
5
6
  const usePsFileText = (url) => {
6
- const [state, setState] = (0, react_1.useState)({ hasFailed: false, text: null });
7
- (0, react_1.useEffect)(() => {
8
- const controller = new AbortController();
9
- setState({ hasFailed: false, text: null });
10
- fetch(url, { credentials: 'include', signal: controller.signal })
11
- .then((response) => {
12
- if (!response.ok)
13
- throw new Error(response.statusText);
14
- return response.text();
15
- })
16
- .then((text) => setState({ hasFailed: false, text }))
17
- .catch(() => {
18
- if (!controller.signal.aborted)
19
- setState({ hasFailed: true, text: null });
20
- });
21
- return () => controller.abort();
22
- }, [url]);
23
- return state;
7
+ const { hasFailed, value } = (0, use_ps_loaded_file_1.usePsLoadedFile)(url, ps_file_fetch_service_1.PsFileFetchService.text);
8
+ return { hasFailed, text: value };
24
9
  };
25
10
  exports.usePsFileText = usePsFileText;
@@ -0,0 +1,2 @@
1
+ import { type RefObject } from 'react';
2
+ export declare const usePsFindShortcut: (scope: RefObject<HTMLElement> | null, isEnabled: boolean, onFind: () => void) => void;
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.usePsFindShortcut = void 0;
4
+ const react_1 = require("react");
5
+ const ps_file_search_service_1 = require("../services/ps-file-search-service");
6
+ const usePsFindShortcut = (scope, isEnabled, onFind) => {
7
+ (0, react_1.useEffect)(() => {
8
+ if (!isEnabled)
9
+ return;
10
+ const onKey = (event) => {
11
+ if (!ps_file_search_service_1.PsFileSearchService.isFindShortcut(event))
12
+ return;
13
+ if (scope !== null) {
14
+ const node = scope.current;
15
+ if (node === null)
16
+ return;
17
+ if (!node.contains(document.activeElement) && !node.matches(':hover'))
18
+ return;
19
+ }
20
+ event.preventDefault();
21
+ onFind();
22
+ };
23
+ window.addEventListener('keydown', onKey);
24
+ return () => window.removeEventListener('keydown', onKey);
25
+ }, [scope, isEnabled, onFind]);
26
+ };
27
+ exports.usePsFindShortcut = usePsFindShortcut;
@@ -0,0 +1,2 @@
1
+ import type { PsLoadedFileState } from '../models/ps-loaded-file-state';
2
+ export declare const usePsLoadedFile: <T>(url: string, load: (url: string, signal: AbortSignal) => Promise<T>) => PsLoadedFileState<T>;
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.usePsLoadedFile = void 0;
4
+ const react_1 = require("react");
5
+ const usePsLoadedFile = (url, load) => {
6
+ const [state, setState] = (0, react_1.useState)({ hasFailed: false, value: null });
7
+ (0, react_1.useEffect)(() => {
8
+ const controller = new AbortController();
9
+ setState({ hasFailed: false, value: null });
10
+ load(url, controller.signal)
11
+ .then((value) => {
12
+ if (!controller.signal.aborted)
13
+ setState({ hasFailed: false, value });
14
+ })
15
+ .catch(() => {
16
+ if (!controller.signal.aborted)
17
+ setState({ hasFailed: true, value: null });
18
+ });
19
+ return () => controller.abort();
20
+ }, [url, load]);
21
+ return state;
22
+ };
23
+ exports.usePsLoadedFile = usePsLoadedFile;
package/dist/index.d.ts CHANGED
@@ -18,6 +18,13 @@ export * from './components/ps-text-viewer';
18
18
  export * from './components/ps-unsupported-viewer';
19
19
  export * from './components/ps-upload-modal';
20
20
  export * from './components/ps-upload-row';
21
+ export * from './components/ps-file-search-bar';
22
+ export * from './components/ps-html-document';
23
+ export * from './components/ps-html-viewer';
24
+ export * from './components/ps-image-text-highlights';
25
+ export * from './components/ps-sheet-viewer';
26
+ export * from './components/ps-table-view';
27
+ export * from './components/ps-word-viewer';
21
28
  export * from './constants/ps-file-icon-button-classes';
22
29
  export * from './constants/ps-file-kind-icons';
23
30
  export * from './constants/ps-file-kind';
@@ -33,6 +40,7 @@ export * from './constants/ps-upload-messages';
33
40
  export * from './constants/ps-upload-queue-config';
34
41
  export * from './constants/ps-upload-status-tones';
35
42
  export * from './constants/ps-upload-status';
43
+ export * from './constants/ps-html-sanitize-config';
36
44
  export * from './models/ps-drag-pan-handlers';
37
45
  export * from './models/ps-drag-pan-options';
38
46
  export * from './models/ps-file-icon-button-tone';
@@ -59,6 +67,20 @@ export * from './models/ps-viewer-file';
59
67
  export * from './models/ps-xhr-response-type';
60
68
  export * from './models/ps-xhr-upload-request';
61
69
  export * from './models/ps-xhr-upload-response';
70
+ export * from './models/ps-file-search-state';
71
+ export * from './models/ps-html-highlight-result';
72
+ export * from './models/ps-image-match';
73
+ export * from './models/ps-image-text-box';
74
+ export * from './models/ps-image-text-layer';
75
+ export * from './models/ps-image-text-word';
76
+ export * from './models/ps-item-match';
77
+ export * from './models/ps-item-match-part';
78
+ export * from './models/ps-loaded-file-state';
79
+ export * from './models/ps-normalized-text';
80
+ export * from './models/ps-pdf-text-item';
81
+ export * from './models/ps-pdf-viewport-like';
82
+ export * from './models/ps-search-item';
83
+ export * from './models/ps-sheet-data';
62
84
  export * from './services/ps-csv-service';
63
85
  export * from './services/ps-file-selection-service';
64
86
  export * from './services/ps-file-size-service';
@@ -67,11 +89,22 @@ export * from './services/ps-pdf-service';
67
89
  export * from './services/ps-text-search-service';
68
90
  export * from './services/ps-upload-queue-service';
69
91
  export * from './services/ps-xhr-upload-service';
92
+ export * from './services/ps-file-fetch-service';
93
+ export * from './services/ps-file-search-service';
94
+ export * from './services/ps-html-file-service';
95
+ export * from './services/ps-html-service';
96
+ export * from './services/ps-image-text-service';
97
+ export * from './services/ps-label-service';
98
+ export * from './services/ps-sheet-service';
99
+ export * from './services/ps-word-service';
70
100
  export * from './hooks/use-ps-active-match-scroll';
71
101
  export * from './hooks/use-ps-drag-pan';
72
102
  export * from './hooks/use-ps-file-text';
73
103
  export * from './hooks/use-ps-in-view';
74
104
  export * from './hooks/use-ps-upload-queue';
105
+ export * from './hooks/use-ps-file-search';
106
+ export * from './hooks/use-ps-find-shortcut';
107
+ export * from './hooks/use-ps-loaded-file';
75
108
  export * from './components/ps-document-scanner';
76
109
  export * from './constants/ps-document-scanner-labels';
77
110
  export * from './constants/ps-scan-format';
package/dist/index.js CHANGED
@@ -34,6 +34,13 @@ __exportStar(require("./components/ps-text-viewer"), exports);
34
34
  __exportStar(require("./components/ps-unsupported-viewer"), exports);
35
35
  __exportStar(require("./components/ps-upload-modal"), exports);
36
36
  __exportStar(require("./components/ps-upload-row"), exports);
37
+ __exportStar(require("./components/ps-file-search-bar"), exports);
38
+ __exportStar(require("./components/ps-html-document"), exports);
39
+ __exportStar(require("./components/ps-html-viewer"), exports);
40
+ __exportStar(require("./components/ps-image-text-highlights"), exports);
41
+ __exportStar(require("./components/ps-sheet-viewer"), exports);
42
+ __exportStar(require("./components/ps-table-view"), exports);
43
+ __exportStar(require("./components/ps-word-viewer"), exports);
37
44
  __exportStar(require("./constants/ps-file-icon-button-classes"), exports);
38
45
  __exportStar(require("./constants/ps-file-kind-icons"), exports);
39
46
  __exportStar(require("./constants/ps-file-kind"), exports);
@@ -49,6 +56,7 @@ __exportStar(require("./constants/ps-upload-messages"), exports);
49
56
  __exportStar(require("./constants/ps-upload-queue-config"), exports);
50
57
  __exportStar(require("./constants/ps-upload-status-tones"), exports);
51
58
  __exportStar(require("./constants/ps-upload-status"), exports);
59
+ __exportStar(require("./constants/ps-html-sanitize-config"), exports);
52
60
  __exportStar(require("./models/ps-drag-pan-handlers"), exports);
53
61
  __exportStar(require("./models/ps-drag-pan-options"), exports);
54
62
  __exportStar(require("./models/ps-file-icon-button-tone"), exports);
@@ -75,6 +83,20 @@ __exportStar(require("./models/ps-viewer-file"), exports);
75
83
  __exportStar(require("./models/ps-xhr-response-type"), exports);
76
84
  __exportStar(require("./models/ps-xhr-upload-request"), exports);
77
85
  __exportStar(require("./models/ps-xhr-upload-response"), exports);
86
+ __exportStar(require("./models/ps-file-search-state"), exports);
87
+ __exportStar(require("./models/ps-html-highlight-result"), exports);
88
+ __exportStar(require("./models/ps-image-match"), exports);
89
+ __exportStar(require("./models/ps-image-text-box"), exports);
90
+ __exportStar(require("./models/ps-image-text-layer"), exports);
91
+ __exportStar(require("./models/ps-image-text-word"), exports);
92
+ __exportStar(require("./models/ps-item-match"), exports);
93
+ __exportStar(require("./models/ps-item-match-part"), exports);
94
+ __exportStar(require("./models/ps-loaded-file-state"), exports);
95
+ __exportStar(require("./models/ps-normalized-text"), exports);
96
+ __exportStar(require("./models/ps-pdf-text-item"), exports);
97
+ __exportStar(require("./models/ps-pdf-viewport-like"), exports);
98
+ __exportStar(require("./models/ps-search-item"), exports);
99
+ __exportStar(require("./models/ps-sheet-data"), exports);
78
100
  __exportStar(require("./services/ps-csv-service"), exports);
79
101
  __exportStar(require("./services/ps-file-selection-service"), exports);
80
102
  __exportStar(require("./services/ps-file-size-service"), exports);
@@ -83,11 +105,22 @@ __exportStar(require("./services/ps-pdf-service"), exports);
83
105
  __exportStar(require("./services/ps-text-search-service"), exports);
84
106
  __exportStar(require("./services/ps-upload-queue-service"), exports);
85
107
  __exportStar(require("./services/ps-xhr-upload-service"), exports);
108
+ __exportStar(require("./services/ps-file-fetch-service"), exports);
109
+ __exportStar(require("./services/ps-file-search-service"), exports);
110
+ __exportStar(require("./services/ps-html-file-service"), exports);
111
+ __exportStar(require("./services/ps-html-service"), exports);
112
+ __exportStar(require("./services/ps-image-text-service"), exports);
113
+ __exportStar(require("./services/ps-label-service"), exports);
114
+ __exportStar(require("./services/ps-sheet-service"), exports);
115
+ __exportStar(require("./services/ps-word-service"), exports);
86
116
  __exportStar(require("./hooks/use-ps-active-match-scroll"), exports);
87
117
  __exportStar(require("./hooks/use-ps-drag-pan"), exports);
88
118
  __exportStar(require("./hooks/use-ps-file-text"), exports);
89
119
  __exportStar(require("./hooks/use-ps-in-view"), exports);
90
120
  __exportStar(require("./hooks/use-ps-upload-queue"), exports);
121
+ __exportStar(require("./hooks/use-ps-file-search"), exports);
122
+ __exportStar(require("./hooks/use-ps-find-shortcut"), exports);
123
+ __exportStar(require("./hooks/use-ps-loaded-file"), exports);
91
124
  __exportStar(require("./components/ps-document-scanner"), exports);
92
125
  __exportStar(require("./constants/ps-document-scanner-labels"), exports);
93
126
  __exportStar(require("./constants/ps-scan-format"), exports);
@@ -0,0 +1,13 @@
1
+ import type { RefObject } from 'react';
2
+ export interface PsFileSearchState {
3
+ activeMatch: number;
4
+ focus: () => void;
5
+ inputRef: RefObject<HTMLInputElement>;
6
+ matchCount: number;
7
+ query: string;
8
+ reset: () => void;
9
+ search: string;
10
+ setMatchCount: (count: number) => void;
11
+ setSearch: (value: string) => void;
12
+ step: (delta: number) => void;
13
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -1,12 +1,14 @@
1
1
  import type { ReactNode } from 'react';
2
2
  import type { PsFileViewerLabels } from '../constants/ps-file-viewer-labels';
3
+ import type { PsImageTextLayer } from './ps-image-text-layer';
3
4
  import type { PsLabelSet } from './ps-label-set';
4
5
  export interface PsFileViewerPaneProps {
5
6
  contentType: string;
6
7
  headerActions?: ReactNode;
7
8
  id?: string;
8
- labels?: PsLabelSet<typeof PsFileViewerLabels>;
9
+ labels?: Partial<PsLabelSet<typeof PsFileViewerLabels>>;
9
10
  name: string;
10
11
  pdfWorkerSrc?: string;
12
+ textLayer?: PsImageTextLayer;
11
13
  url: string;
12
14
  }
@@ -0,0 +1,4 @@
1
+ export interface PsHtmlHighlightResult {
2
+ count: number;
3
+ html: string;
4
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,4 @@
1
+ export interface PsHtmlTextNode {
2
+ node: Text;
3
+ offset: number;
4
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,7 @@
1
+ export interface PsImageMatch {
2
+ height: number;
3
+ left: number;
4
+ matchIndex: number;
5
+ top: number;
6
+ width: number;
7
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ import type { TextLayerBox } from '@pallasoft/ps-utilities';
2
+ export type PsImageTextBox = TextLayerBox;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ import type { TextLayer } from '@pallasoft/ps-utilities';
2
+ export type PsImageTextLayer = TextLayer;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ import type { TextLayerWord } from '@pallasoft/ps-utilities';
2
+ export type PsImageTextWord = TextLayerWord;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ import type { TextItemMatchPart } from '@pallasoft/ps-utilities';
2
+ export type PsItemMatchPart = TextItemMatchPart;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,2 @@
1
+ import type { TextItemMatch } from '@pallasoft/ps-utilities';
2
+ export type PsItemMatch = TextItemMatch;