@jc-times/business-ui 0.2.43

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 (154) hide show
  1. package/AGENTS.md +6 -0
  2. package/CHANGELOG.md +267 -0
  3. package/README.md +55 -0
  4. package/THIRD_PARTY_NOTICES.md +29 -0
  5. package/bin/business-ui-gate.mjs +171 -0
  6. package/dist/Alert.js +47 -0
  7. package/dist/AsyncDirectoryPicker.js +134 -0
  8. package/dist/AsyncSearchPicker.js +155 -0
  9. package/dist/AutoComplete.js +34 -0
  10. package/dist/Badge.js +14 -0
  11. package/dist/Button.js +54 -0
  12. package/dist/Cascader.js +141 -0
  13. package/dist/Combobox.js +106 -0
  14. package/dist/ConfirmDialog.js +48 -0
  15. package/dist/DataTableHorizontalScrollbar.js +38 -0
  16. package/dist/DataTableIcons.js +37 -0
  17. package/dist/DataTableMergedRows.js +45 -0
  18. package/dist/DataTableTheme.js +135 -0
  19. package/dist/DateInput.js +223 -0
  20. package/dist/DropdownMenu.js +130 -0
  21. package/dist/EmptyState.js +27 -0
  22. package/dist/ExplainableButton.js +68 -0
  23. package/dist/FileDropzone.js +70 -0
  24. package/dist/FilePreparationDialog.js +33 -0
  25. package/dist/FloatingControls.js +120 -0
  26. package/dist/FormField.js +143 -0
  27. package/dist/MetricCard.js +38 -0
  28. package/dist/ModalShell.js +139 -0
  29. package/dist/MultiSelect.js +137 -0
  30. package/dist/NumericInput.js +97 -0
  31. package/dist/OverlayContainer.js +9 -0
  32. package/dist/PageHeader.js +36 -0
  33. package/dist/Pagination.js +115 -0
  34. package/dist/PreparedFileDropzone.js +30 -0
  35. package/dist/RecoverableAsyncState.js +35 -0
  36. package/dist/RovingTabs.js +54 -0
  37. package/dist/SectionCard.js +35 -0
  38. package/dist/SegmentedControl.js +46 -0
  39. package/dist/Select.js +73 -0
  40. package/dist/Skeleton.js +25 -0
  41. package/dist/SortableList.js +55 -0
  42. package/dist/StructuredAddressInput.js +157 -0
  43. package/dist/Toast.js +100 -0
  44. package/dist/ToggleSwitch.js +34 -0
  45. package/dist/TreeSelect.js +444 -0
  46. package/dist/amount-format.js +20 -0
  47. package/dist/business-ui.js +44 -0
  48. package/dist/chinese-address-regions.js +15 -0
  49. package/dist/classNames.js +6 -0
  50. package/dist/data-table.js +257 -0
  51. package/dist/document-render-budget.js +22 -0
  52. package/dist/document-viewer/ContinuousPdfViewer.js +145 -0
  53. package/dist/document-viewer/DocumentViewer.js +123 -0
  54. package/dist/document-viewer/DocumentViewerViewport.js +36 -0
  55. package/dist/document-viewer/ImagePage.js +39 -0
  56. package/dist/document-viewer/PdfCanvasPage.js +26 -0
  57. package/dist/document-viewer/PdfThumbnailRail.js +116 -0
  58. package/dist/document-viewer/PdfToolbar.js +61 -0
  59. package/dist/document-viewer/PdfWorkspace.js +42 -0
  60. package/dist/document-viewer/pdf-render-budget.js +7 -0
  61. package/dist/document-viewer/usePdfCanvas.js +69 -0
  62. package/dist/document-viewer/usePdfViewport.js +48 -0
  63. package/dist/document-viewer-v2/DocumentViewerV2.js +171 -0
  64. package/dist/document-viewer-v2/HeadlessPdfViewer.js +420 -0
  65. package/dist/document-viewer-v2/HeadlessSearch.js +66 -0
  66. package/dist/document-viewer-v2.js +13 -0
  67. package/dist/document-viewer.js +12 -0
  68. package/dist/pdfium-viewer.js +18 -0
  69. package/dist/styles.css +2 -0
  70. package/dist/types/Alert.d.ts +11 -0
  71. package/dist/types/AmountFormat.d.ts +15 -0
  72. package/dist/types/AsyncDirectoryPicker.d.ts +32 -0
  73. package/dist/types/AsyncSearchPicker.d.ts +26 -0
  74. package/dist/types/AutoComplete.d.ts +9 -0
  75. package/dist/types/Badge.d.ts +13 -0
  76. package/dist/types/Button.d.ts +36 -0
  77. package/dist/types/Cascader.d.ts +57 -0
  78. package/dist/types/ChineseAddressRegions.d.ts +4 -0
  79. package/dist/types/Combobox.d.ts +37 -0
  80. package/dist/types/ConfirmDialog.d.ts +20 -0
  81. package/dist/types/DataTable.d.ts +68 -0
  82. package/dist/types/DataTableHorizontalScrollbar.d.ts +8 -0
  83. package/dist/types/DataTableIcons.d.ts +19 -0
  84. package/dist/types/DataTableMergedRows.d.ts +11 -0
  85. package/dist/types/DataTableTheme.d.ts +4 -0
  86. package/dist/types/DateInput.d.ts +25 -0
  87. package/dist/types/DocumentRenderBudget.d.ts +9 -0
  88. package/dist/types/DocumentViewer.d.ts +11 -0
  89. package/dist/types/DocumentViewerV2.d.ts +10 -0
  90. package/dist/types/DropdownMenu.d.ts +73 -0
  91. package/dist/types/EmptyState.d.ts +9 -0
  92. package/dist/types/ExplainableButton.d.ts +7 -0
  93. package/dist/types/FileDropzone.d.ts +20 -0
  94. package/dist/types/FilePreparationDialog.d.ts +12 -0
  95. package/dist/types/FloatingControls.d.ts +39 -0
  96. package/dist/types/FormField.d.ts +35 -0
  97. package/dist/types/MetricCard.d.ts +17 -0
  98. package/dist/types/ModalShell.d.ts +33 -0
  99. package/dist/types/MultiSelect.d.ts +12 -0
  100. package/dist/types/NumericInput.d.ts +54 -0
  101. package/dist/types/OverlayContainer.d.ts +2 -0
  102. package/dist/types/PageHeader.d.ts +23 -0
  103. package/dist/types/Pagination.d.ts +14 -0
  104. package/dist/types/PdfiumViewer.d.ts +5 -0
  105. package/dist/types/PreparedFileDropzone.d.ts +7 -0
  106. package/dist/types/RecoverableAsyncState.d.ts +11 -0
  107. package/dist/types/RovingTabs.d.ts +21 -0
  108. package/dist/types/SectionCard.d.ts +18 -0
  109. package/dist/types/SegmentedControl.d.ts +26 -0
  110. package/dist/types/Select.d.ts +31 -0
  111. package/dist/types/Skeleton.d.ts +11 -0
  112. package/dist/types/SortableList.d.ts +17 -0
  113. package/dist/types/StructuredAddressInput.d.ts +57 -0
  114. package/dist/types/Toast.d.ts +22 -0
  115. package/dist/types/ToggleSwitch.d.ts +15 -0
  116. package/dist/types/TreeSelect.d.ts +58 -0
  117. package/dist/types/classNames.d.ts +1 -0
  118. package/dist/types/document-viewer/ContinuousPdfViewer.d.ts +16 -0
  119. package/dist/types/document-viewer/DocumentViewer.d.ts +31 -0
  120. package/dist/types/document-viewer/DocumentViewerViewport.d.ts +23 -0
  121. package/dist/types/document-viewer/ImagePage.d.ts +9 -0
  122. package/dist/types/document-viewer/PdfCanvasPage.d.ts +7 -0
  123. package/dist/types/document-viewer/PdfThumbnailRail.d.ts +12 -0
  124. package/dist/types/document-viewer/PdfToolbar.d.ts +13 -0
  125. package/dist/types/document-viewer/PdfWorkspace.d.ts +5 -0
  126. package/dist/types/document-viewer/pdf-render-budget.d.ts +2 -0
  127. package/dist/types/document-viewer/usePdfCanvas.d.ts +22 -0
  128. package/dist/types/document-viewer/usePdfViewport.d.ts +14 -0
  129. package/dist/types/document-viewer-v2/DocumentViewerV2.d.ts +50 -0
  130. package/dist/types/document-viewer-v2/HeadlessPdfViewer.d.ts +39 -0
  131. package/dist/types/document-viewer-v2/HeadlessSearch.d.ts +9 -0
  132. package/dist/types/index.d.ts +41 -0
  133. package/dist/types/useDebouncedValue.d.ts +2 -0
  134. package/dist/types/useFilePreparation.d.ts +28 -0
  135. package/dist/types/useModalFocusTrap.d.ts +3 -0
  136. package/dist/useDebouncedValue.js +16 -0
  137. package/dist/useFilePreparation.js +51 -0
  138. package/dist/useModalFocusTrap.js +71 -0
  139. package/docs/agent-guide.md +145 -0
  140. package/docs/api.md +220 -0
  141. package/docs/cascader.md +56 -0
  142. package/docs/component-strategy.md +94 -0
  143. package/docs/data-table.md +123 -0
  144. package/docs/dependencies.md +57 -0
  145. package/docs/document-viewer-v2.md +259 -0
  146. package/docs/document-viewer.md +28 -0
  147. package/docs/file-preparation.md +11 -0
  148. package/docs/maturity-migration.md +62 -0
  149. package/docs/modal-shell-migration.md +43 -0
  150. package/docs/mrt-poc.md +205 -0
  151. package/docs/release.md +32 -0
  152. package/docs/viewport-qa.md +99 -0
  153. package/licenses/rc-cascader-MIT.txt +21 -0
  154. package/package.json +163 -0
@@ -0,0 +1,257 @@
1
+ import { EmptyState as e } from "./EmptyState.js";
2
+ import { Skeleton as t } from "./Skeleton.js";
3
+ import { DataTableTheme as n } from "./DataTableTheme.js";
4
+ import { icons as r } from "./DataTableIcons.js";
5
+ import { DataTableHorizontalScrollbar as i } from "./DataTableHorizontalScrollbar.js";
6
+ import { DataTableMergedRows as a } from "./DataTableMergedRows.js";
7
+ import { ArrowDown as o, ArrowUp as s, ChevronsUpDown as c } from "lucide-react";
8
+ import { memo as l, useCallback as u, useMemo as d, useRef as f, useState as p } from "react";
9
+ import { jsx as m, jsxs as h } from "react/jsx-runtime";
10
+ import { MRT_Table as g, MaterialReactTable as _, useMaterialReactTable as v } from "material-react-table";
11
+ import { MRT_Localization_ZH_HANS as y } from "material-react-table/locales/zh-Hans";
12
+ //#region src/DataTable.tsx
13
+ var b = new Intl.Collator("zh-CN", {
14
+ numeric: !0,
15
+ sensitivity: "base"
16
+ });
17
+ function x(e) {
18
+ return v({
19
+ localization: y,
20
+ icons: r,
21
+ ...e
22
+ });
23
+ }
24
+ function S({ table: e, stickyHorizontalScrollbar: t = !1, horizontalScrollbarLabel: r }) {
25
+ return /* @__PURE__ */ m(n, { children: /* @__PURE__ */ m(i, {
26
+ enabled: t,
27
+ label: r,
28
+ children: /* @__PURE__ */ m(_, { table: e })
29
+ }) });
30
+ }
31
+ function C(e) {
32
+ return "options" in e ? /* @__PURE__ */ m(w, { ...e }) : /* @__PURE__ */ m(n, { children: /* @__PURE__ */ m(T, { ...e }) });
33
+ }
34
+ function w({ options: e, stickyHorizontalScrollbar: t, horizontalScrollbarLabel: n }) {
35
+ let r = x(e);
36
+ return /* @__PURE__ */ m(S, {
37
+ table: r,
38
+ stickyHorizontalScrollbar: t,
39
+ horizontalScrollbarLabel: n
40
+ });
41
+ }
42
+ function T({ rows: n, columns: r, getRowId: a, caption: o, sort: s, defaultSort: c = null, onSortChange: l, sortMode: _ = "client", selectionSummary: y = !0, selectPageLabel: b = "选择本页全部", renderSelectionActions: x, hiddenColumnIds: S, selectedRowIds: C, onSelectedRowIdsChange: w, getRowDisabled: T, loading: D = !1, loadingRows: O = 4, emptyTitle: j = "暂无数据", emptyDescription: M, emptyAction: N, mobileLayout: P = "scroll", className: F = "", stickyHorizontalScrollbar: I = !1, horizontalScrollbarLabel: L, rootRef: R, rootProps: z, tableRef: B, tableProps: V }) {
43
+ let [H, U] = p(c), W = s === void 0 ? H : s, G = d(() => _ === "server" ? n : E(n, r, W), [
44
+ n,
45
+ r,
46
+ W,
47
+ _
48
+ ]), K = d(() => r.filter((e) => !S?.has(e.id)), [r, S]), q = d(() => G.map((e) => ({
49
+ row: e,
50
+ id: a(e),
51
+ disabled: T?.(e) ?? !1
52
+ })), [
53
+ G,
54
+ a,
55
+ T
56
+ ]), J = d(() => q.filter((e) => !e.disabled), [q]), Y = d(() => {
57
+ let e = 0;
58
+ for (let t of J) C?.has(t.id) && (e += 1);
59
+ return e;
60
+ }, [J, C]), X = J.length > 0 && Y === J.length, Z = Y > 0 && !X;
61
+ function te(e) {
62
+ if (!(e.sortValue || _ === "server" && e.sortable)) return;
63
+ let t = W?.columnId === e.id ? W.direction === "ascending" ? {
64
+ columnId: e.id,
65
+ direction: "descending"
66
+ } : null : {
67
+ columnId: e.id,
68
+ direction: "ascending"
69
+ };
70
+ U(t), l?.(t);
71
+ }
72
+ let Q = f({
73
+ selectedRowIds: C,
74
+ onSelectedRowIdsChange: w
75
+ });
76
+ Q.current = {
77
+ selectedRowIds: C,
78
+ onSelectedRowIdsChange: w
79
+ };
80
+ let ne = u((e) => {
81
+ let t = Q.current;
82
+ if (!t.onSelectedRowIdsChange) return;
83
+ let n = new Set(t.selectedRowIds ?? []);
84
+ n.has(e) ? n.delete(e) : n.add(e), t.onSelectedRowIdsChange(n);
85
+ }, []);
86
+ function re() {
87
+ if (!w) return;
88
+ let e = new Set(C ?? []);
89
+ for (let t of J) X ? e.delete(t.id) : e.add(t.id);
90
+ w(e);
91
+ }
92
+ let $ = !!(C && w), ie = d(() => [...$ ? [{
93
+ id: "__selection",
94
+ header: "",
95
+ size: 44,
96
+ Header: () => /* @__PURE__ */ m(A, {
97
+ checked: X,
98
+ indeterminate: Z,
99
+ "aria-label": b,
100
+ disabled: D || !J.length,
101
+ onChange: re
102
+ })
103
+ }] : [], ...K.map((e) => ({
104
+ id: e.id,
105
+ header: typeof e.header == "string" ? e.header : e.mobileLabel ?? e.id,
106
+ Header: () => {
107
+ let t = W?.columnId === e.id ? W.direction : void 0;
108
+ return e.sortValue || _ === "server" && e.sortable ? /* @__PURE__ */ h("button", {
109
+ type: "button",
110
+ className: "ui-table-sort",
111
+ onClick: () => te(e),
112
+ children: [e.header, /* @__PURE__ */ m(k, { direction: t })]
113
+ }) : e.header;
114
+ },
115
+ muiTableHeadCellProps: {
116
+ style: { width: e.width },
117
+ "data-align": e.align ?? "start",
118
+ "aria-sort": W?.columnId === e.id ? W.direction : e.sortValue || _ === "server" && e.sortable ? "none" : void 0
119
+ }
120
+ }))], [
121
+ K,
122
+ $,
123
+ X,
124
+ Z,
125
+ C,
126
+ D,
127
+ W,
128
+ _,
129
+ J,
130
+ b,
131
+ l,
132
+ w
133
+ ]), ae = v({
134
+ columns: ie,
135
+ data: G,
136
+ getRowId: (e) => a(e),
137
+ enableSorting: !1,
138
+ enableColumnActions: !1,
139
+ enableColumnFilters: !1,
140
+ enableGlobalFilter: !1,
141
+ enablePagination: !1,
142
+ enableTopToolbar: !1,
143
+ enableBottomToolbar: !1,
144
+ enableTableFooter: !1,
145
+ layoutMode: "semantic",
146
+ renderCaption: o === void 0 ? void 0 : () => o,
147
+ muiTableProps: {
148
+ ...V,
149
+ ref: B,
150
+ className: "ui-data-table",
151
+ "aria-busy": D || void 0
152
+ },
153
+ muiTableBodyProps: { children: D ? Array.from({ length: Math.max(1, O) }, (e, n) => /* @__PURE__ */ h("tr", { children: [$ && /* @__PURE__ */ m("td", {
154
+ className: "ui-table-selection",
155
+ children: /* @__PURE__ */ m(t, {
156
+ width: 18,
157
+ height: 18
158
+ })
159
+ }), K.map((e) => /* @__PURE__ */ m("td", { children: /* @__PURE__ */ m(t, { width: n % 2 ? "68%" : "86%" }) }, e.id))] }, `loading-${n}`)) : q.map(({ row: e, id: t, disabled: n }) => /* @__PURE__ */ m(ee, {
160
+ row: e,
161
+ id: t,
162
+ disabled: n,
163
+ columns: K,
164
+ selectable: $,
165
+ selected: C?.has(t) ?? !1,
166
+ onToggle: ne
167
+ }, t)) }
168
+ });
169
+ return /* @__PURE__ */ h("div", {
170
+ ...z,
171
+ ref: R,
172
+ "data-mobile-layout": P,
173
+ className: `ui-data-table-wrap ${F}`.trim(),
174
+ children: [
175
+ $ && C && C.size > 0 && (y || x) && /* @__PURE__ */ h("div", {
176
+ className: "ui-table-selection-summary",
177
+ children: [y && /* @__PURE__ */ h("span", {
178
+ role: "status",
179
+ children: [
180
+ "已选择 ",
181
+ C.size,
182
+ " 项(本页 ",
183
+ Y,
184
+ " 项)"
185
+ ]
186
+ }), x?.(C)]
187
+ }),
188
+ /* @__PURE__ */ m(i, {
189
+ enabled: I,
190
+ label: L,
191
+ children: /* @__PURE__ */ m(g, { table: ae })
192
+ }),
193
+ !D && G.length === 0 && /* @__PURE__ */ m(e, {
194
+ compact: !0,
195
+ title: j,
196
+ description: M,
197
+ action: N
198
+ })
199
+ ]
200
+ });
201
+ }
202
+ function E(e, t, n) {
203
+ if (!n) return [...e];
204
+ let r = t.find((e) => e.id === n.columnId);
205
+ if (!r?.sortValue) return [...e];
206
+ let i = n.direction === "ascending" ? 1 : -1;
207
+ return e.map((e, t) => ({
208
+ row: e,
209
+ index: t,
210
+ value: r.sortValue(e)
211
+ })).sort((e, t) => {
212
+ let n = O(e.value, t.value);
213
+ return n === 0 ? e.index - t.index : n * i;
214
+ }).map(({ row: e }) => e);
215
+ }
216
+ function D({ row: e, id: t, disabled: n, columns: r, selectable: i, selected: a, onToggle: o }) {
217
+ return /* @__PURE__ */ h("tr", {
218
+ "aria-selected": a || void 0,
219
+ "data-disabled": n || void 0,
220
+ children: [i && /* @__PURE__ */ m("td", {
221
+ className: "ui-table-selection",
222
+ children: /* @__PURE__ */ m("input", {
223
+ type: "checkbox",
224
+ "aria-label": `选择 ${t}`,
225
+ checked: a,
226
+ disabled: n,
227
+ onChange: () => o(t)
228
+ })
229
+ }), r.map((t) => /* @__PURE__ */ m("td", {
230
+ "data-align": t.align ?? "start",
231
+ "data-label": t.mobileLabel ?? (typeof t.header == "string" ? t.header : void 0),
232
+ children: t.cell(e)
233
+ }, t.id))]
234
+ });
235
+ }
236
+ var ee = l(D);
237
+ function O(e, t) {
238
+ if (e == null && t == null) return 0;
239
+ if (e == null) return 1;
240
+ if (t == null) return -1;
241
+ let n = e instanceof Date ? e.getTime() : e, r = t instanceof Date ? t.getTime() : t;
242
+ return typeof n == "number" && typeof r == "number" ? n - r : b.compare(String(n), String(r));
243
+ }
244
+ function k({ direction: e }) {
245
+ return m(e === "ascending" ? s : e === "descending" ? o : c, { size: 14 });
246
+ }
247
+ function A({ indeterminate: e, ...t }) {
248
+ return /* @__PURE__ */ m("input", {
249
+ ...t,
250
+ type: "checkbox",
251
+ ref: (t) => {
252
+ t && (t.indeterminate = e);
253
+ }
254
+ });
255
+ }
256
+ //#endregion
257
+ export { C as DataTable, a as DataTableMergedRows, n as DataTableTheme, S as DataTableView, E as sortRows, x as useDataTable };
@@ -0,0 +1,22 @@
1
+ //#region src/DocumentRenderBudget.ts
2
+ function e(e, t) {
3
+ return t || e <= 900 ? {
4
+ maxDevicePixelRatio: 1,
5
+ maxCanvasPixels: 12e5,
6
+ overscanPixels: 80,
7
+ neighboringPages: 0,
8
+ preloadOffsets: [1]
9
+ } : {
10
+ maxDevicePixelRatio: 1.75,
11
+ maxCanvasPixels: 4e6,
12
+ overscanPixels: 520,
13
+ neighboringPages: 1,
14
+ preloadOffsets: [-1, 1]
15
+ };
16
+ }
17
+ function t(e, t, n, r) {
18
+ let i = Math.sqrt(r.maxCanvasPixels / Math.max(1, e * t)) * .999;
19
+ return Math.max(.1, Math.min(n || 1, r.maxDevicePixelRatio, i));
20
+ }
21
+ //#endregion
22
+ export { t as constrainedPixelRatio, e as getPdfRenderBudget };
@@ -0,0 +1,145 @@
1
+ import { pdfRenderBudgetForWindow as e } from "./pdf-render-budget.js";
2
+ import { PdfCanvasPage as t } from "./PdfCanvasPage.js";
3
+ import { useEffect as n, useRef as r, useState as i } from "react";
4
+ import { jsx as a, jsxs as o } from "react/jsx-runtime";
5
+ //#region src/document-viewer/ContinuousPdfViewer.tsx
6
+ var s = /* @__PURE__ */ new WeakMap();
7
+ function c({ document: s, pages: c, currentPage: d, onCurrentPageChange: f, zoom: p = 1, rotation: m = 0, focusTarget: h, renderPage: g }) {
8
+ let _ = r(null), v = r(/* @__PURE__ */ new Map()), y = r(0), b = r(""), x = r(0), S = r(0), C = r(d), w = r({
9
+ currentPage: d,
10
+ onCurrentPageChange: f
11
+ });
12
+ w.current = {
13
+ currentPage: d,
14
+ onCurrentPageChange: f
15
+ };
16
+ let T = `${p}:${m}`, E = r(T), D = r(null);
17
+ C.current = d, E.current !== T && (E.current = T, D.current = d);
18
+ let [O, k] = i(() => /* @__PURE__ */ new Set([d, d + 1]));
19
+ n(() => {
20
+ k(new Set([C.current, C.current + 1].filter((e) => e <= s.numPages)));
21
+ }, [s]), n(() => {
22
+ let e = requestAnimationFrame(A);
23
+ return () => cancelAnimationFrame(e);
24
+ }, [s, c]), n(() => {
25
+ let e = _.current;
26
+ if (!e || typeof ResizeObserver > "u") return;
27
+ let t = new ResizeObserver(j);
28
+ return t.observe(e), () => t.disconnect();
29
+ }, [s]), n(() => {
30
+ let e = h?.page === d && h.token !== b.current ? h : null;
31
+ if (y.current === d && !e) {
32
+ y.current = 0;
33
+ return;
34
+ }
35
+ k((e) => /* @__PURE__ */ new Set([...e, d]));
36
+ let t = _.current, n = v.current.get(d);
37
+ if (!t || !n) return;
38
+ let r = t.getBoundingClientRect(), i = n.querySelector(".pdf-page")?.getBoundingClientRect() ?? n.getBoundingClientRect(), a = i.top - r.top + t.scrollTop, o = e ? a + i.height * e.y - t.clientHeight / 2 : a;
39
+ e && (b.current = e.token), t.scrollTo({
40
+ top: Math.max(0, Math.min(o, t.scrollHeight - t.clientHeight)),
41
+ behavior: "auto"
42
+ });
43
+ }, [
44
+ s,
45
+ d,
46
+ h
47
+ ]), n(() => {
48
+ let e = D.current;
49
+ if (e === null) return;
50
+ D.current = null, S.current = performance.now() + 350;
51
+ let t = globalThis.setTimeout(() => {
52
+ if (C.current !== e) return;
53
+ let t = _.current, n = v.current.get(e);
54
+ if (!t || !n) return;
55
+ let r = t.getBoundingClientRect(), i = n.getBoundingClientRect();
56
+ t.scrollTo({
57
+ top: i.top - r.top + t.scrollTop,
58
+ behavior: "auto"
59
+ });
60
+ }, 100);
61
+ return () => globalThis.clearTimeout(t);
62
+ }, [
63
+ s,
64
+ p,
65
+ m
66
+ ]), n(() => u(s, e().preloadOffsets.map((e) => d + e)), [s, d]), n(() => () => {
67
+ x.current && cancelAnimationFrame(x.current);
68
+ }, []);
69
+ function A() {
70
+ if (performance.now() < S.current) return;
71
+ let t = _.current;
72
+ if (!t) return;
73
+ let n = t.getBoundingClientRect(), r = n.top + 26, i = e(), a = w.current.currentPage, o = Infinity, u = /* @__PURE__ */ new Set();
74
+ for (let [e, t] of v.current) {
75
+ let s = t.getBoundingClientRect();
76
+ s.bottom >= n.top - i.overscanPixels && s.top <= n.bottom + i.overscanPixels && u.add(e);
77
+ let c = Math.abs(s.top - r);
78
+ c < o && (o = c, a = e);
79
+ }
80
+ t.scrollTop > 0 && t.scrollHeight - t.clientHeight - t.scrollTop < 2 && (a = c[c.length - 1] ?? a);
81
+ for (let e = -i.neighboringPages; e <= i.neighboringPages; e += 1) {
82
+ let t = a + e;
83
+ t >= 1 && t <= s.numPages && u.add(t);
84
+ }
85
+ k((e) => l(e, u) ? e : u), a !== w.current.currentPage && (y.current = a, w.current.onCurrentPageChange(a));
86
+ }
87
+ function j() {
88
+ x.current && cancelAnimationFrame(x.current), x.current = requestAnimationFrame(A);
89
+ }
90
+ return /* @__PURE__ */ a("div", {
91
+ ref: _,
92
+ className: "ui-continuous-scroll",
93
+ onScroll: j,
94
+ children: c.map((e) => /* @__PURE__ */ o("div", {
95
+ "data-page": e,
96
+ ref: (t) => {
97
+ t ? v.current.set(e, t) : v.current.delete(e);
98
+ },
99
+ className: "ui-continuous-page",
100
+ style: { width: `min(${760 * p}px, ${p * 100}%)` },
101
+ children: [/* @__PURE__ */ o("span", { children: [
102
+ "第 ",
103
+ e,
104
+ " 页"
105
+ ] }), O.has(e) ? g?.(e) ?? /* @__PURE__ */ a(t, {
106
+ document: s,
107
+ page: e,
108
+ renderWidth: 760 * p,
109
+ rotation: m
110
+ }) : /* @__PURE__ */ a("div", {
111
+ className: "ui-page-placeholder",
112
+ style: { aspectRatio: m % 180 ? "1.414 / 1" : "1 / 1.414" }
113
+ })]
114
+ }, e))
115
+ });
116
+ }
117
+ function l(e, t) {
118
+ return e.size === t.size && [...e].every((e) => t.has(e));
119
+ }
120
+ function u(e, t) {
121
+ let n = !1, r = d(() => {
122
+ (async () => {
123
+ for (let r of t) {
124
+ if (n) return;
125
+ if (r < 1 || r > e.numPages) continue;
126
+ let t = s.get(e);
127
+ t || (t = /* @__PURE__ */ new Map(), s.set(e, t)), t.has(r) || t.set(r, e.getPage(r).then((e) => e.getOperatorList()).then(() => void 0).catch(() => void 0)), await t.get(r);
128
+ }
129
+ })();
130
+ });
131
+ return () => {
132
+ n = !0, r();
133
+ };
134
+ }
135
+ function d(e, t = 1200) {
136
+ let n = window;
137
+ if (typeof n.requestIdleCallback == "function") {
138
+ let r = n.requestIdleCallback(e, { timeout: t });
139
+ return () => n.cancelIdleCallback?.(r);
140
+ }
141
+ let r = globalThis.setTimeout(e, 180);
142
+ return () => globalThis.clearTimeout(r);
143
+ }
144
+ //#endregion
145
+ export { c as ContinuousPdfViewer };
@@ -0,0 +1,123 @@
1
+ import { Button as e } from "../Button.js";
2
+ import { OverlayContainerContext as t } from "../OverlayContainer.js";
3
+ import { PdfWorkspace as n } from "./PdfWorkspace.js";
4
+ import { DocumentViewerViewport as r } from "./DocumentViewerViewport.js";
5
+ import { ImagePage as i } from "./ImagePage.js";
6
+ import { PdfThumbnailRail as a } from "./PdfThumbnailRail.js";
7
+ import { PdfToolbar as o } from "./PdfToolbar.js";
8
+ import { usePdfViewport as s } from "./usePdfViewport.js";
9
+ import { useMemo as c, useState as l } from "react";
10
+ import { jsx as u, jsxs as d } from "react/jsx-runtime";
11
+ //#region src/document-viewer/DocumentViewer.tsx
12
+ function f(e) {
13
+ return /* @__PURE__ */ u(p, { ...e }, `${e.source.kind}:${e.source.id}`);
14
+ }
15
+ function p({ source: f, title: p, className: m = "", style: h, ariaLabel: g = "文档查看器", toolbar: _, footer: v, currentPage: y, onCurrentPageChange: b, pageMode: x = "continuous", renderPage: S }) {
16
+ let C = s(f.id), [w, T] = l(1), E = f.kind === "pdf" ? f.document.numPages : f.images.length, D = Math.max(1, Math.min(E, y ?? w)), O = c(() => Array.from({ length: E }, (e, t) => t + 1), [E]), k = (e) => {
17
+ T(e), b?.(e);
18
+ };
19
+ return /* @__PURE__ */ u("section", {
20
+ ref: C.containerRef,
21
+ "aria-label": g,
22
+ style: h,
23
+ className: `ui-document-viewer ${C.fullscreen ? "ui-viewer-fullscreen" : ""} ${m}`,
24
+ children: /* @__PURE__ */ d(t.Provider, {
25
+ value: C.containerRef.current,
26
+ children: [
27
+ /* @__PURE__ */ d("div", {
28
+ className: "ui-viewer-toolbar",
29
+ children: [
30
+ p !== void 0 && /* @__PURE__ */ u("div", {
31
+ className: "ui-viewer-title",
32
+ children: p
33
+ }),
34
+ _,
35
+ /* @__PURE__ */ u(o, {
36
+ zoom: C.zoom,
37
+ disabled: !E,
38
+ fullscreen: C.fullscreen,
39
+ canZoomIn: C.canZoomIn,
40
+ canZoomOut: C.canZoomOut,
41
+ onZoomIn: C.zoomIn,
42
+ onZoomOut: C.zoomOut,
43
+ onRotate: C.rotate,
44
+ onToggleFullscreen: C.toggleFullscreen
45
+ })
46
+ ]
47
+ }),
48
+ E ? f.kind === "pdf" ? /* @__PURE__ */ u(r, {
49
+ document: f.document,
50
+ pages: O,
51
+ pageMode: x,
52
+ currentPage: D,
53
+ onCurrentPageChange: k,
54
+ zoom: C.zoom,
55
+ rotation: C.rotation,
56
+ rail: /* @__PURE__ */ u(a, {
57
+ document: f.document,
58
+ currentPage: D,
59
+ onCurrentPageChange: k
60
+ }),
61
+ renderPage: S ? (e) => S({
62
+ page: e,
63
+ zoom: C.zoom,
64
+ rotation: C.rotation
65
+ }) : void 0
66
+ }) : /* @__PURE__ */ u(n, {
67
+ rail: /* @__PURE__ */ u("div", {
68
+ className: "ui-thumbnail-list",
69
+ children: f.images.map((t, n) => /* @__PURE__ */ d(e, {
70
+ variant: "ghost",
71
+ className: "ui-page-thumbnail",
72
+ "aria-current": D === n + 1 ? "page" : void 0,
73
+ onClick: () => k(n + 1),
74
+ children: [/* @__PURE__ */ u("img", {
75
+ src: t.src,
76
+ alt: "",
77
+ loading: "lazy"
78
+ }), /* @__PURE__ */ u("span", { children: t.alt || `图片 ${n + 1}` })]
79
+ }, `${n}:${t.src}`))
80
+ }),
81
+ children: /* @__PURE__ */ u(i, {
82
+ image: f.images[D - 1],
83
+ zoom: C.zoom,
84
+ rotation: C.rotation
85
+ }, f.images[D - 1].src)
86
+ }) : /* @__PURE__ */ u("div", {
87
+ role: "status",
88
+ children: "没有可预览的页面"
89
+ }),
90
+ /* @__PURE__ */ d("div", {
91
+ className: "ui-viewer-footer",
92
+ children: [
93
+ /* @__PURE__ */ u(e, {
94
+ variant: "ghost",
95
+ size: "compact",
96
+ disabled: D <= 1,
97
+ onClick: () => k(D - 1),
98
+ children: "上一页"
99
+ }),
100
+ /* @__PURE__ */ d("span", {
101
+ "aria-live": "polite",
102
+ children: [
103
+ E ? D : 0,
104
+ " / ",
105
+ E
106
+ ]
107
+ }),
108
+ /* @__PURE__ */ u(e, {
109
+ variant: "ghost",
110
+ size: "compact",
111
+ disabled: D >= E,
112
+ onClick: () => k(D + 1),
113
+ children: "下一页"
114
+ }),
115
+ v
116
+ ]
117
+ })
118
+ ]
119
+ })
120
+ });
121
+ }
122
+ //#endregion
123
+ export { f as DocumentViewer };
@@ -0,0 +1,36 @@
1
+ import { PdfCanvasPage as e } from "./PdfCanvasPage.js";
2
+ import { ContinuousPdfViewer as t } from "./ContinuousPdfViewer.js";
3
+ import { PdfWorkspace as n } from "./PdfWorkspace.js";
4
+ import { Fragment as r, jsx as i, jsxs as a } from "react/jsx-runtime";
5
+ //#region src/document-viewer/DocumentViewerViewport.tsx
6
+ function o({ document: o, pageMode: s, pages: c, currentPage: l, onCurrentPageChange: u, zoom: d = 1, rotation: f = 0, rail: p, overlay: m, className: h = "", workspaceClassName: g = "", workspaceProps: _, focusTarget: v, renderPage: y }) {
7
+ let b = /* @__PURE__ */ a(r, { children: [m, s === "continuous" ? /* @__PURE__ */ i(t, {
8
+ document: o,
9
+ pages: c,
10
+ currentPage: l,
11
+ onCurrentPageChange: u,
12
+ zoom: d,
13
+ rotation: f,
14
+ focusTarget: v,
15
+ renderPage: y
16
+ }) : /* @__PURE__ */ i("div", {
17
+ className: "ui-single-page",
18
+ children: y?.(l) ?? /* @__PURE__ */ i(e, {
19
+ document: o,
20
+ page: l,
21
+ renderWidth: 760 * d,
22
+ rotation: f
23
+ })
24
+ })] });
25
+ return p === void 0 ? /* @__PURE__ */ i("div", {
26
+ className: `ui-document-viewport ${h}`,
27
+ children: b
28
+ }) : /* @__PURE__ */ i(n, {
29
+ ..._,
30
+ rail: p,
31
+ className: `${g} ${h}`,
32
+ children: b
33
+ });
34
+ }
35
+ //#endregion
36
+ export { o as DocumentViewerViewport };
@@ -0,0 +1,39 @@
1
+ import { useState as e } from "react";
2
+ import { jsx as t } from "react/jsx-runtime";
3
+ //#region src/document-viewer/ImagePage.tsx
4
+ function n({ image: n, zoom: r, rotation: i }) {
5
+ let [a, o] = e({
6
+ width: 760,
7
+ height: 560
8
+ }), [s, c] = e(!1), l = i % 180 != 0, u = l ? a.height : a.width, d = l ? a.width : a.height;
9
+ return /* @__PURE__ */ t("div", {
10
+ className: "ui-image-scroll",
11
+ children: s ? /* @__PURE__ */ t("div", {
12
+ role: "alert",
13
+ children: "图片加载失败,请检查文件是否可用。"
14
+ }) : /* @__PURE__ */ t("div", {
15
+ className: "ui-image-frame",
16
+ style: {
17
+ width: `min(${Math.min(u, 1e3) * r}px, ${100 * r}%)`,
18
+ aspectRatio: `${u} / ${d}`
19
+ },
20
+ children: /* @__PURE__ */ t("img", {
21
+ src: n.src,
22
+ alt: n.alt,
23
+ draggable: !1,
24
+ decoding: "async",
25
+ style: {
26
+ width: l ? `${a.width / a.height * 100}%` : "100%",
27
+ transform: `translate(-50%, -50%) rotate(${i}deg)`
28
+ },
29
+ onLoad: (e) => o({
30
+ width: e.currentTarget.naturalWidth,
31
+ height: e.currentTarget.naturalHeight
32
+ }),
33
+ onError: () => c(!0)
34
+ })
35
+ })
36
+ });
37
+ }
38
+ //#endregion
39
+ export { n as ImagePage };
@@ -0,0 +1,26 @@
1
+ import { usePdfCanvas as e } from "./usePdfCanvas.js";
2
+ import { jsx as t, jsxs as n } from "react/jsx-runtime";
3
+ //#region src/document-viewer/PdfCanvasPage.tsx
4
+ function r({ document: r, page: i, renderWidth: a = 760, rotation: o = 0 }) {
5
+ let { canvasRef: s, ratio: c, error: l } = e({
6
+ kind: "page",
7
+ document: r,
8
+ page: i,
9
+ renderWidth: a,
10
+ rotation: o,
11
+ zoom: 1
12
+ });
13
+ return /* @__PURE__ */ n("div", {
14
+ className: "ui-pdf-page",
15
+ style: { aspectRatio: `${1 / c}` },
16
+ children: [/* @__PURE__ */ t("canvas", {
17
+ ref: s,
18
+ "aria-label": `第 ${i} 页`
19
+ }), l && /* @__PURE__ */ t("div", {
20
+ role: "alert",
21
+ children: l
22
+ })]
23
+ });
24
+ }
25
+ //#endregion
26
+ export { r as PdfCanvasPage };