@embedpdf/viewer-chrome 3.0.0-next.14 → 3.0.0-next.16

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 (177) hide show
  1. package/README.md +175 -132
  2. package/dist/annotation-fonts-DWjVOTP0.js +80 -0
  3. package/dist/annotation-fonts-DWjVOTP0.js.map +1 -0
  4. package/dist/annotation-fonts-dpfVkhnq.cjs +91 -0
  5. package/dist/annotation-fonts-dpfVkhnq.cjs.map +1 -0
  6. package/dist/annotation-style-B3XKAyZ-.cjs +879 -0
  7. package/dist/annotation-style-B3XKAyZ-.cjs.map +1 -0
  8. package/dist/annotation-style-CXF3X47Z.js +879 -0
  9. package/dist/annotation-style-CXF3X47Z.js.map +1 -0
  10. package/dist/ar-B132r9bo.cjs +659 -0
  11. package/dist/ar-B132r9bo.cjs.map +1 -0
  12. package/dist/ar-BLWFJoA_.js +659 -0
  13. package/dist/ar-BLWFJoA_.js.map +1 -0
  14. package/dist/attachments-panel-Cxln8xos.cjs +217 -0
  15. package/dist/attachments-panel-Cxln8xos.cjs.map +1 -0
  16. package/dist/attachments-panel-H1ucRbwo.js +217 -0
  17. package/dist/attachments-panel-H1ucRbwo.js.map +1 -0
  18. package/dist/chrome.cjs +399 -242
  19. package/dist/chrome.cjs.map +1 -1
  20. package/dist/chrome.d.cts +5 -35
  21. package/dist/chrome.d.ts +5 -35
  22. package/dist/chrome.js +398 -239
  23. package/dist/chrome.js.map +1 -1
  24. package/dist/commands-BkgLP3Om.js +1348 -0
  25. package/dist/commands-BkgLP3Om.js.map +1 -0
  26. package/dist/commands-DL1gjZt7.cjs +1473 -0
  27. package/dist/commands-DL1gjZt7.cjs.map +1 -0
  28. package/dist/commands.cjs +13 -649
  29. package/dist/commands.d.cts +30 -3
  30. package/dist/commands.d.ts +30 -3
  31. package/dist/commands.js +2 -647
  32. package/dist/comments-panel-BsnWedTh.cjs +514 -0
  33. package/dist/comments-panel-BsnWedTh.cjs.map +1 -0
  34. package/dist/comments-panel-D7Eadws9.js +514 -0
  35. package/dist/comments-panel-D7Eadws9.js.map +1 -0
  36. package/dist/de-7_MvFWzN.cjs +658 -0
  37. package/dist/de-7_MvFWzN.cjs.map +1 -0
  38. package/dist/de-BUhwc9-x.js +658 -0
  39. package/dist/de-BUhwc9-x.js.map +1 -0
  40. package/dist/dialog-BIb373cg.js +55 -0
  41. package/dist/dialog-BIb373cg.js.map +1 -0
  42. package/dist/dialog-CngKTnAM.cjs +60 -0
  43. package/dist/dialog-CngKTnAM.cjs.map +1 -0
  44. package/dist/es-DgYj-1L3.cjs +658 -0
  45. package/dist/es-DgYj-1L3.cjs.map +1 -0
  46. package/dist/es-DoXTqFoO.js +658 -0
  47. package/dist/es-DoXTqFoO.js.map +1 -0
  48. package/dist/form-design-panel-CgV_5YWC.js +418 -0
  49. package/dist/form-design-panel-CgV_5YWC.js.map +1 -0
  50. package/dist/form-design-panel-D0FdmWXW.cjs +418 -0
  51. package/dist/form-design-panel-D0FdmWXW.cjs.map +1 -0
  52. package/dist/fr-B-8NDhBA.js +658 -0
  53. package/dist/fr-B-8NDhBA.js.map +1 -0
  54. package/dist/fr-C856dmQJ.cjs +658 -0
  55. package/dist/fr-C856dmQJ.cjs.map +1 -0
  56. package/dist/he-BFTeNc4t.cjs +659 -0
  57. package/dist/he-BFTeNc4t.cjs.map +1 -0
  58. package/dist/he-Dlh0fNXM.js +659 -0
  59. package/dist/he-Dlh0fNXM.js.map +1 -0
  60. package/dist/icons-1UfLUZ_y.cjs +1029 -0
  61. package/dist/icons-1UfLUZ_y.cjs.map +1 -0
  62. package/dist/icons-7dB0Y1ct.js +875 -0
  63. package/dist/icons-7dB0Y1ct.js.map +1 -0
  64. package/dist/index.cjs +3651 -5447
  65. package/dist/index.cjs.map +1 -1
  66. package/dist/index.d.cts +646 -144
  67. package/dist/index.d.ts +646 -144
  68. package/dist/index.js +3618 -5368
  69. package/dist/index.js.map +1 -1
  70. package/dist/it-Bef-2Yxq.cjs +658 -0
  71. package/dist/it-Bef-2Yxq.cjs.map +1 -0
  72. package/dist/it-BkirG7ol.js +658 -0
  73. package/dist/it-BkirG7ol.js.map +1 -0
  74. package/dist/ja-CGEjCE-s.js +658 -0
  75. package/dist/ja-CGEjCE-s.js.map +1 -0
  76. package/dist/ja-DNw2zqSD.cjs +658 -0
  77. package/dist/ja-DNw2zqSD.cjs.map +1 -0
  78. package/dist/ko-CTkl5vMh.js +658 -0
  79. package/dist/ko-CTkl5vMh.js.map +1 -0
  80. package/dist/ko-YHzeBqP6.cjs +658 -0
  81. package/dist/ko-YHzeBqP6.cjs.map +1 -0
  82. package/dist/labels-BiM9wp9K.cjs +21 -0
  83. package/dist/labels-BiM9wp9K.cjs.map +1 -0
  84. package/dist/labels-C6_i87Oj.js +16 -0
  85. package/dist/labels-C6_i87Oj.js.map +1 -0
  86. package/dist/link-editor-CAS7MZM2.cjs +125 -0
  87. package/dist/link-editor-CAS7MZM2.cjs.map +1 -0
  88. package/dist/link-editor-CkwtqRvb.js +125 -0
  89. package/dist/link-editor-CkwtqRvb.js.map +1 -0
  90. package/dist/measurement-CQdbnIrn.js +325 -0
  91. package/dist/measurement-CQdbnIrn.js.map +1 -0
  92. package/dist/measurement-Cxv1Ahxx.cjs +326 -0
  93. package/dist/measurement-Cxv1Ahxx.cjs.map +1 -0
  94. package/dist/nl-BjkbaLq3.cjs +658 -0
  95. package/dist/nl-BjkbaLq3.cjs.map +1 -0
  96. package/dist/nl-Dya4sR8_.js +658 -0
  97. package/dist/nl-Dya4sR8_.js.map +1 -0
  98. package/dist/outline-panel-BpGtBdj0.cjs +707 -0
  99. package/dist/outline-panel-BpGtBdj0.cjs.map +1 -0
  100. package/dist/outline-panel-DO5_REYw.js +707 -0
  101. package/dist/outline-panel-DO5_REYw.js.map +1 -0
  102. package/dist/outline-properties-BCa2cc0t.js +330 -0
  103. package/dist/outline-properties-BCa2cc0t.js.map +1 -0
  104. package/dist/outline-properties-DT3FIxCw.cjs +330 -0
  105. package/dist/outline-properties-DT3FIxCw.cjs.map +1 -0
  106. package/dist/pl-CKKdVnpZ.cjs +658 -0
  107. package/dist/pl-CKKdVnpZ.cjs.map +1 -0
  108. package/dist/pl-DA9b5NVg.js +658 -0
  109. package/dist/pl-DA9b5NVg.js.map +1 -0
  110. package/dist/print-dialog-BqIrHCBh.cjs +276 -0
  111. package/dist/print-dialog-BqIrHCBh.cjs.map +1 -0
  112. package/dist/print-dialog-DvcI2m2_.js +276 -0
  113. package/dist/print-dialog-DvcI2m2_.js.map +1 -0
  114. package/dist/pt-DLcszlzi.cjs +658 -0
  115. package/dist/pt-DLcszlzi.cjs.map +1 -0
  116. package/dist/pt-Nm8yyjbX.js +658 -0
  117. package/dist/pt-Nm8yyjbX.js.map +1 -0
  118. package/dist/redact-confirm-C6EiK8yN.cjs +83 -0
  119. package/dist/redact-confirm-C6EiK8yN.cjs.map +1 -0
  120. package/dist/redact-confirm-CKuv9iN_.js +83 -0
  121. package/dist/redact-confirm-CKuv9iN_.js.map +1 -0
  122. package/dist/redaction-panel-CgNZ-pQk.js +96 -0
  123. package/dist/redaction-panel-CgNZ-pQk.js.map +1 -0
  124. package/dist/redaction-panel-ZhX0dlMi.cjs +96 -0
  125. package/dist/redaction-panel-ZhX0dlMi.cjs.map +1 -0
  126. package/dist/search-panel-BE4xzWlm.js +249 -0
  127. package/dist/search-panel-BE4xzWlm.js.map +1 -0
  128. package/dist/search-panel-wcbTNG1z.cjs +249 -0
  129. package/dist/search-panel-wcbTNG1z.cjs.map +1 -0
  130. package/dist/sheet-DTBFiwde.cjs +461 -0
  131. package/dist/sheet-DTBFiwde.cjs.map +1 -0
  132. package/dist/sheet-DyjKfAq0.js +378 -0
  133. package/dist/sheet-DyjKfAq0.js.map +1 -0
  134. package/dist/sign-dialog-D5WGx-Yn.cjs +155 -0
  135. package/dist/sign-dialog-D5WGx-Yn.cjs.map +1 -0
  136. package/dist/sign-dialog-DerNe8qT.js +155 -0
  137. package/dist/sign-dialog-DerNe8qT.js.map +1 -0
  138. package/dist/signature-inspector-Bz6TAfZM.cjs +160 -0
  139. package/dist/signature-inspector-Bz6TAfZM.cjs.map +1 -0
  140. package/dist/signature-inspector-CsGr9EBk.js +160 -0
  141. package/dist/signature-inspector-CsGr9EBk.js.map +1 -0
  142. package/dist/signature-maker-D_YfBXLn.cjs +393 -0
  143. package/dist/signature-maker-D_YfBXLn.cjs.map +1 -0
  144. package/dist/signature-maker-Dnth4rV4.js +393 -0
  145. package/dist/signature-maker-Dnth4rV4.js.map +1 -0
  146. package/dist/signatures-panel-Ci_LaI1C.cjs +294 -0
  147. package/dist/signatures-panel-Ci_LaI1C.cjs.map +1 -0
  148. package/dist/signatures-panel-DZ9ywrjz.js +294 -0
  149. package/dist/signatures-panel-DZ9ywrjz.js.map +1 -0
  150. package/dist/stamp-store-BHvRs-Do.cjs +147 -0
  151. package/dist/stamp-store-BHvRs-Do.cjs.map +1 -0
  152. package/dist/stamp-store-WuF-L3Jj.js +112 -0
  153. package/dist/stamp-store-WuF-L3Jj.js.map +1 -0
  154. package/dist/stamps-panel-BrczStaz.js +225 -0
  155. package/dist/stamps-panel-BrczStaz.js.map +1 -0
  156. package/dist/stamps-panel-Cv9nJBwx.cjs +225 -0
  157. package/dist/stamps-panel-Cv9nJBwx.cjs.map +1 -0
  158. package/dist/theme-Be0OZokZ.js +97 -0
  159. package/dist/theme-Be0OZokZ.js.map +1 -0
  160. package/dist/theme-FR26JI3r.cjs +126 -0
  161. package/dist/theme-FR26JI3r.cjs.map +1 -0
  162. package/dist/toolbar-DF361xWY.js +1565 -0
  163. package/dist/toolbar-DF361xWY.js.map +1 -0
  164. package/dist/toolbar-ddvpsvTb.cjs +1660 -0
  165. package/dist/toolbar-ddvpsvTb.cjs.map +1 -0
  166. package/dist/zh-cn-BMPPkLpL.js +658 -0
  167. package/dist/zh-cn-BMPPkLpL.js.map +1 -0
  168. package/dist/zh-cn-CZOO3p4H.cjs +658 -0
  169. package/dist/zh-cn-CZOO3p4H.cjs.map +1 -0
  170. package/package.json +6 -4
  171. package/src/styles.css +161 -89
  172. package/dist/commands.cjs.map +0 -1
  173. package/dist/commands.js.map +0 -1
  174. package/dist/es-BXLlBo2b.cjs +0 -321
  175. package/dist/es-BXLlBo2b.cjs.map +0 -1
  176. package/dist/es-CLgTsFDS.js +0 -321
  177. package/dist/es-CLgTsFDS.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outline-panel-DO5_REYw.js","names":[],"sources":["../src/ui/outline-tree.ts","../src/ui/outline-rows.tsx","../src/ui/outline-panel.tsx"],"sourcesContent":["/**\n * The outline panel's rules, as plain functions: which rows a filter shows,\n * whether an item's own colour reads on the panel, and where a dragged row\n * lands. The panel (outline-panel.tsx) draws what these say.\n */\nimport type {\n OutlineItem,\n OutlineItemRef,\n OutlinePosition,\n OutlineRow,\n} from '@embedpdf/react/outline';\n\n/** A row's height, in px: every row has the same, so the list draws only the rows in view. */\nexport const OUTLINE_ROW_HEIGHT = 30;\n/** How far each level is indented, in px. */\nexport const OUTLINE_INDENT = 16;\n\nexport const outlineKeyOf = (ref: OutlineItemRef | null): string =>\n ref ? String(ref.objectNumber) : 'top';\n\n/**\n * The rows a filter shows: every item whose title holds the text, whatever its case, with the\n * items it sits under so it is found in its place. Every shown parent shows its children.\n */\nexport function filteredRows(items: readonly OutlineItem[], query: string): OutlineRow[] {\n const needle = query.trim().toLocaleLowerCase();\n if (!needle) return [];\n const byKey = new Map(items.map((item) => [outlineKeyOf(item.ref), item]));\n const shown = new Set<string>();\n for (const item of items) {\n if (!item.title.toLocaleLowerCase().includes(needle)) continue;\n for (let at: OutlineItem | undefined = item; at; ) {\n const key = outlineKeyOf(at.ref);\n if (shown.has(key)) break;\n shown.add(key);\n at = at.parent ? byKey.get(outlineKeyOf(at.parent)) : undefined;\n }\n }\n const depthOf = new Map<string, number>();\n const parents = new Set(\n items.flatMap((item) => (item.parent ? [outlineKeyOf(item.parent)] : [])),\n );\n const rows: OutlineRow[] = [];\n for (const item of items) {\n const key = outlineKeyOf(item.ref);\n const depth = item.parent ? (depthOf.get(outlineKeyOf(item.parent)) ?? -1) + 1 : 0;\n depthOf.set(key, depth);\n if (!shown.has(key)) continue;\n const hasChildren = parents.has(key);\n rows.push({ item, depth, hasChildren, expanded: hasChildren });\n }\n return rows;\n}\n\n/** The panel's background in each mode, as the viewer's theme draws it. */\nconst SURFACE = { light: '#ffffff', dark: '#1f2937' } as const;\n\n/** WCAG's least contrast for large or bold text, and for parts of a picture. */\nconst LEAST_CONTRAST = 3;\n\n/** A `#rrggbb` colour's relative luminance (WCAG 2.2, \"relative luminance\"). */\nfunction luminanceOf(color: string): number {\n const value = Number.parseInt(color.slice(1), 16);\n const channel = (shift: number) => {\n const level = ((value >> shift) & 0xff) / 255;\n return level <= 0.04045 ? level / 12.92 : ((level + 0.055) / 1.055) ** 2.4;\n };\n return 0.2126 * channel(16) + 0.7152 * channel(8) + 0.0722 * channel(0);\n}\n\n/**\n * The colour to draw an item's title in: its own (`/C`), unless it would read badly on the\n * panel (a dark red in the dark theme, yellow in the light one); then the panel's own text\n * colour, as for an item without one.\n */\nexport function readableColor(color: string | null, mode: 'light' | 'dark'): string | null {\n if (!color || !/^#[0-9a-fA-F]{6}$/.test(color)) return null;\n const [lighter, darker] = [luminanceOf(color), luminanceOf(SURFACE[mode])].sort(\n (left, right) => right - left,\n );\n return (lighter! + 0.05) / (darker! + 0.05) >= LEAST_CONTRAST ? color : null;\n}\n\n/** Where a dragged row lands: its new parent and place, and the level the line is drawn at. */\nexport interface OutlineDrop {\n readonly parent: OutlineItemRef | null;\n readonly position: OutlinePosition;\n readonly depth: number;\n}\n\n/**\n * The keys of the rows that move with `dragged`: each dragged row and the rows under it that\n * show. A drop among them would put an item under itself.\n */\nexport function movingKeysOf(\n rows: readonly OutlineRow[],\n dragged: ReadonlySet<string>,\n): Set<string> {\n const moving = new Set<string>();\n let under = -1;\n for (const row of rows) {\n const key = outlineKeyOf(row.item.ref);\n if (under >= 0 && row.depth > under) {\n moving.add(key);\n continue;\n }\n under = -1;\n if (dragged.has(key)) {\n moving.add(key);\n under = row.depth;\n }\n }\n return moving;\n}\n\n/**\n * Where rows dropped in the gap before `rows[gap]` land, at the level the pointer asks for\n * (`depth`), as a tree view lets them: no deeper than one level under the row above, and no\n * shallower than the row below, so the tree stays a tree. `moving` are the rows that move: the\n * gaps among them are left out. `null` when no row stays to place them by.\n */\nexport function dropOf(\n rows: readonly OutlineRow[],\n moving: ReadonlySet<string>,\n gap: number,\n depth: number,\n): OutlineDrop | null {\n const kept = rows.filter((row) => !moving.has(outlineKeyOf(row.item.ref)));\n if (kept.length === 0) return null;\n const at = rows.slice(0, gap).filter((row) => !moving.has(outlineKeyOf(row.item.ref))).length;\n const above = kept[at - 1];\n const below = kept[at];\n const deepest = above ? above.depth + 1 : 0;\n const shallowest = below ? Math.min(below.depth, deepest) : 0;\n const level = Math.max(shallowest, Math.min(deepest, Math.round(depth)));\n let parent: OutlineItemRef | null = null;\n let previous: OutlineItemRef | null = null;\n for (let i = at - 1; i >= 0; i -= 1) {\n const row = kept[i]!;\n if (row.depth < level) {\n parent = row.item.ref;\n break;\n }\n if (row.depth === level && previous === null) previous = row.item.ref;\n }\n return { parent, position: previous ? { after: previous } : 'start', depth: level };\n}\n","/**\n * The outline's rows: a tree that draws only the rows in view (every row is one height), with\n * the keyboard of the ARIA tree pattern (`treeKeyAction`), renaming in the row, and dragging rows\n * to another place, the pointer's distance from the edge choosing how deep. A pen or a finger\n * holds a row first, so a swipe still scrolls the list.\n */\nimport { treeKeyAction, type TreeKeyAction } from '@embedpdf/core-ui';\nimport { useCommand } from '@embedpdf/react/commands';\nimport { useT } from '@embedpdf/react/i18n';\nimport type { OutlineCapability, OutlineItemRef, OutlineRow } from '@embedpdf/react/outline';\nimport {\n useEffect,\n useId,\n useLayoutEffect,\n useRef,\n useState,\n type KeyboardEvent as ReactKeyboardEvent,\n type MouseEvent as ReactMouseEvent,\n type PointerEvent as ReactPointerEvent,\n} from 'react';\n\nimport { Icon } from './icons';\nimport {\n OUTLINE_INDENT,\n OUTLINE_ROW_HEIGHT,\n dropOf,\n movingKeysOf,\n outlineKeyOf,\n readableColor,\n type OutlineDrop,\n} from './outline-tree';\nimport { CommandButton } from './toolbar';\n\n/** Rows drawn past each edge of the view, so a scroll shows no gap before the next frame. */\nconst OVERSCAN = 8;\n/** How far the pointer moves before a press on a row becomes a drag, in px. */\nconst DRAG_SLOP_PX = 4;\n/** How long a pen or a finger holds a row before it drags it, in ms. */\nconst HOLD_MS = 450;\n/** Within this many px of the list's top or bottom, a drag scrolls the list. */\nconst EDGE_PX = 28;\n/** The text of a row is drawn at this size, in px. */\nconst TEXT_PX = 13;\n/** A text field below this size makes iOS zoom the page as it takes focus. */\nconst FIELD_PX = 16;\n\nexport interface OutlineRowsProps {\n readonly outline: OutlineCapability;\n readonly rows: readonly OutlineRow[];\n /** The row that shows where the main view is reading: the current item, or its shown parent. */\n readonly currentKey: string | null;\n readonly selected: readonly OutlineItemRef[];\n /** Whether the rows can be renamed, dragged and deleted. */\n readonly editable: boolean;\n /** Rows show as found by a filter: none of them folds, and none drags. */\n readonly filtering: boolean;\n readonly renamingKey: string | null;\n readonly onRename: (key: string | null) => void;\n readonly mode: 'light' | 'dark';\n /** An item was followed: the panel closes when it covers the pages. */\n readonly onPicked: () => void;\n readonly label: string;\n}\n\ninterface Drag {\n readonly pointerId: number;\n readonly startX: number;\n readonly startY: number;\n /** The level of the row the drag started on: a drag straight down keeps it. */\n readonly startDepth: number;\n /** The rows that move, by key, and the refs to move, in outline order. */\n readonly moving: ReadonlySet<string>;\n readonly refs: readonly OutlineItemRef[];\n readonly active: boolean;\n readonly drop: (OutlineDrop & { readonly gap: number }) | null;\n}\n\nexport function OutlineRows(props: OutlineRowsProps) {\n const { outline, rows, currentKey, selected, editable, filtering, renamingKey, onRename } = props;\n const t = useT();\n const idPrefix = useId();\n const list = useRef<HTMLDivElement>(null);\n const [scrollTop, setScrollTop] = useState(0);\n const [height, setHeight] = useState(0);\n const [focusedKey, setFocusedKey] = useState<string | null>(null);\n const [anchorKey, setAnchorKey] = useState<string | null>(null);\n const [drag, setDrag] = useState<Drag | null>(null);\n // The focused row is marked only while the keyboard works the tree, not after a click.\n const [treeFocused, setTreeFocused] = useState(false);\n const dragRef = useRef<Drag | null>(null);\n dragRef.current = drag;\n const holdTimer = useRef<ReturnType<typeof setTimeout> | null>(null);\n const suppressClick = useRef(false);\n\n const selectedKeys = new Set(selected.map(outlineKeyOf));\n const indexOfKey = (key: string | null) =>\n key === null ? -1 : rows.findIndex((row) => outlineKeyOf(row.item.ref) === key);\n\n // The keyboard starts where the reader is, else at the selection, else at the top.\n const focused =\n indexOfKey(focusedKey) >= 0\n ? focusedKey\n : (currentKey ?? (selected[0] ? outlineKeyOf(selected[0]) : null));\n const focusedIndex = indexOfKey(focused);\n\n useLayoutEffect(() => {\n const element = list.current;\n if (!element) return;\n const observer = new ResizeObserver(() => setHeight(element.clientHeight));\n observer.observe(element);\n setHeight(element.clientHeight);\n return () => observer.disconnect();\n }, []);\n\n /** Scroll so a row shows, moving no more than it takes. */\n const reveal = (index: number) => {\n const element = list.current;\n if (!element || index < 0) return;\n const top = index * OUTLINE_ROW_HEIGHT;\n if (top < element.scrollTop) element.scrollTop = top;\n else if (top + OUTLINE_ROW_HEIGHT > element.scrollTop + element.clientHeight) {\n element.scrollTop = top + OUTLINE_ROW_HEIGHT - element.clientHeight;\n }\n };\n\n // The reading position moved: its row comes into view.\n const currentIndex = indexOfKey(currentKey);\n useEffect(() => reveal(currentIndex), [currentIndex]);\n // A rename starts on a row that may be scrolled away, such as one an add just made.\n const renamingIndex = indexOfKey(renamingKey);\n useEffect(() => reveal(renamingIndex), [renamingIndex]);\n\n const first = Math.max(0, Math.floor(scrollTop / OUTLINE_ROW_HEIGHT) - OVERSCAN);\n const last = Math.min(\n rows.length,\n Math.ceil((scrollTop + height) / OUTLINE_ROW_HEIGHT) + OVERSCAN,\n );\n\n const follow = (row: OutlineRow) => {\n const { item } = row;\n if (!item.target && !item.action) return;\n outline.activate(item.ref);\n props.onPicked();\n };\n\n const focusRow = (index: number, select: boolean) => {\n const row = rows[index];\n if (!row) return;\n const key = outlineKeyOf(row.item.ref);\n setFocusedKey(key);\n if (select) {\n setAnchorKey(key);\n outline.select([row.item.ref]);\n }\n reveal(index);\n };\n\n const run = (action: TreeKeyAction) => {\n switch (action.type) {\n case 'focus':\n focusRow(action.row, true);\n return;\n case 'expand':\n for (const index of action.rows) {\n const row = rows[index];\n if (row) outline.expand(row.item.ref);\n }\n return;\n case 'collapse': {\n const row = rows[action.row];\n if (row) outline.collapse(row.item.ref);\n return;\n }\n case 'activate': {\n const row = rows[action.row];\n if (row) follow(row);\n return;\n }\n case 'rename': {\n const row = rows[action.row];\n if (row) onRename(outlineKeyOf(row.item.ref));\n return;\n }\n case 'delete':\n if (selected.length > 0) void outline.delete(selected).catch(() => {});\n return;\n }\n };\n\n const onKeyDown = (event: ReactKeyboardEvent<HTMLDivElement>) => {\n if (event.target !== event.currentTarget) return;\n setTreeFocused(true);\n // Backspace is the Delete key of a Mac keyboard.\n const key = event.key === 'Backspace' ? 'Delete' : event.key;\n const action = treeKeyAction(rows, focusedIndex, key, { editable });\n // A filter shows every parent open: there is nothing to fold.\n if (!action || (filtering && (action.type === 'expand' || action.type === 'collapse'))) {\n return;\n }\n event.preventDefault();\n run(action);\n };\n\n const onRowClick = (row: OutlineRow, index: number, event: ReactMouseEvent) => {\n if (suppressClick.current) {\n suppressClick.current = false;\n return;\n }\n const key = outlineKeyOf(row.item.ref);\n setFocusedKey(key);\n if (event.metaKey || event.ctrlKey) {\n // Cmd or Ctrl adds the row to the selection, or takes it out.\n outline.select(\n selectedKeys.has(key)\n ? selected.filter((ref) => outlineKeyOf(ref) !== key)\n : [...selected, row.item.ref],\n );\n setAnchorKey(key);\n return;\n }\n if (event.shiftKey && anchorKey !== null && indexOfKey(anchorKey) >= 0) {\n // Shift selects every row from the last one picked to this one.\n const from = indexOfKey(anchorKey);\n const [low, high] = from < index ? [from, index] : [index, from];\n outline.select(rows.slice(low, high + 1).map((each) => each.item.ref));\n return;\n }\n setAnchorKey(key);\n outline.select([row.item.ref]);\n follow(row);\n };\n\n // ── dragging ──────────────────────────────────────────────────────────────\n\n const stopHold = () => {\n if (holdTimer.current !== null) clearTimeout(holdTimer.current);\n holdTimer.current = null;\n };\n\n /** Where the pointer drops what's dragged, from where it is over the list. */\n const dropAt = (current: Drag, clientX: number, clientY: number): Drag['drop'] => {\n const element = list.current;\n if (!element) return null;\n const box = element.getBoundingClientRect();\n const y = clientY - box.top + element.scrollTop;\n const gap = Math.max(0, Math.min(rows.length, Math.round(y / OUTLINE_ROW_HEIGHT)));\n // Each indent the pointer moves toward the line's end goes a level deeper, back a level shallower.\n const rtl = getComputedStyle(element).direction === 'rtl';\n const across = (clientX - current.startX) * (rtl ? -1 : 1);\n const drop = dropOf(rows, current.moving, gap, current.startDepth + across / OUTLINE_INDENT);\n return drop ? { ...drop, gap } : null;\n };\n\n const startDrag = (current: Drag, clientX: number, clientY: number) => {\n const next = { ...current, active: true, drop: dropAt(current, clientX, clientY) };\n setDrag(next);\n list.current?.setPointerCapture(current.pointerId);\n };\n\n const onPointerDown = (row: OutlineRow, event: ReactPointerEvent) => {\n if (!editable || filtering || event.button !== 0 || renamingKey !== null) return;\n if ((event.target as HTMLElement).closest('button, input')) return;\n const key = outlineKeyOf(row.item.ref);\n // A selected row drags the whole selection with it; any other row drags alone.\n const dragged = selectedKeys.has(key) ? selectedKeys : new Set([key]);\n const moving = movingKeysOf(rows, dragged);\n const refs = rows\n .filter((each) => dragged.has(outlineKeyOf(each.item.ref)))\n .filter((each) => {\n // An item under another dragged one goes with it: name only the topmost.\n const keyOf = outlineKeyOf(each.item.ref);\n const parent = each.item.parent ? outlineKeyOf(each.item.parent) : null;\n return !(parent !== null && moving.has(parent) && moving.has(keyOf));\n })\n .map((each) => each.item.ref);\n const pending: Drag = {\n pointerId: event.pointerId,\n startX: event.clientX,\n startY: event.clientY,\n startDepth: row.depth,\n moving,\n refs,\n active: false,\n drop: null,\n };\n setDrag(pending);\n if (event.pointerType !== 'mouse') {\n const { clientX, clientY } = event;\n holdTimer.current = setTimeout(() => {\n const current = dragRef.current;\n if (current && !current.active) startDrag(current, clientX, clientY);\n }, HOLD_MS);\n }\n };\n\n // While a finger drags, the list must not scroll under it.\n const dragging = drag?.active === true;\n useEffect(() => {\n if (!dragging) return;\n const prevent = (event: TouchEvent) => event.preventDefault();\n document.addEventListener('touchmove', prevent, { passive: false });\n return () => document.removeEventListener('touchmove', prevent);\n }, [dragging]);\n\n const onPointerMove = (event: ReactPointerEvent) => {\n const current = dragRef.current;\n if (!current || event.pointerId !== current.pointerId) return;\n const moved = Math.hypot(event.clientX - current.startX, event.clientY - current.startY);\n if (!current.active) {\n if (moved <= DRAG_SLOP_PX) return;\n if (event.pointerType === 'mouse') startDrag(current, event.clientX, event.clientY);\n else {\n // A finger that moves before the hold is up scrolls the list.\n stopHold();\n setDrag(null);\n }\n return;\n }\n const element = list.current;\n if (element) {\n const box = element.getBoundingClientRect();\n if (event.clientY < box.top + EDGE_PX) element.scrollTop -= 8;\n else if (event.clientY > box.bottom - EDGE_PX) element.scrollTop += 8;\n }\n setDrag({ ...current, drop: dropAt(current, event.clientX, event.clientY) });\n };\n\n const endDrag = (event: ReactPointerEvent, commit: boolean) => {\n stopHold();\n const current = dragRef.current;\n if (!current || event.pointerId !== current.pointerId) return;\n setDrag(null);\n if (!current.active) return;\n // The click a drag ends with is not a click on a row. None comes when the drag ends off\n // the row it began on, so the flag lasts only until this event is done.\n suppressClick.current = true;\n setTimeout(() => {\n suppressClick.current = false;\n }, 0);\n if (commit && current.drop && current.refs.length > 0) {\n void outline.move(current.refs, current.drop.parent, current.drop.position).catch(() => {});\n }\n };\n\n useEffect(() => stopHold, []);\n\n const shown = rows.slice(first, last);\n return (\n <div\n ref={list}\n role=\"tree\"\n aria-label={props.label}\n aria-multiselectable={true}\n tabIndex={0}\n aria-activedescendant={focusedIndex >= 0 ? `${idPrefix}-${focused}` : undefined}\n onKeyDown={onKeyDown}\n onFocus={(event) =>\n event.target === event.currentTarget &&\n setTreeFocused(event.currentTarget.matches(':focus-visible'))\n }\n onBlur={(event) => event.target === event.currentTarget && setTreeFocused(false)}\n onScroll={(event) => setScrollTop(event.currentTarget.scrollTop)}\n onPointerMove={onPointerMove}\n onPointerUp={(event) => endDrag(event, true)}\n onPointerCancel={(event) => endDrag(event, false)}\n className=\"focus-visible:ring-accent relative min-h-0 flex-1 overflow-y-auto outline-none focus-visible:ring-2 focus-visible:ring-inset\"\n >\n <div style={{ height: rows.length * OUTLINE_ROW_HEIGHT, position: 'relative' }}>\n {shown.map((row, offset) => {\n const index = first + offset;\n const key = outlineKeyOf(row.item.ref);\n return (\n <Row\n key={key}\n id={`${idPrefix}-${key}`}\n outline={outline}\n row={row}\n index={index}\n current={key === currentKey}\n selected={selectedKeys.has(key)}\n focused={treeFocused && key === focused}\n moving={dragging && drag.moving.has(key)}\n editable={editable}\n foldable={!filtering}\n renaming={key === renamingKey}\n mode={props.mode}\n untitled={t('outline.untitled')}\n onClick={(event) => onRowClick(row, index, event)}\n onPointerDown={(event) => onPointerDown(row, event)}\n onRenameStart={() => onRename(key)}\n onRenameEnd={() => {\n // The keyboard goes back to the tree, on the row just renamed.\n onRename(null);\n setFocusedKey(key);\n list.current?.focus({ preventScroll: true });\n }}\n onMenu={() => {\n setFocusedKey(key);\n if (!selectedKeys.has(key)) outline.select([row.item.ref]);\n }}\n />\n );\n })}\n {dragging && drag.drop && (\n <div\n aria-hidden\n className=\"bg-accent pointer-events-none absolute h-0.5 rounded-full\"\n style={{\n top: drag.drop.gap * OUTLINE_ROW_HEIGHT - 1,\n insetInlineStart: 4 + 20 + drag.drop.depth * OUTLINE_INDENT,\n insetInlineEnd: 4,\n }}\n />\n )}\n </div>\n </div>\n );\n}\n\ninterface RowProps {\n readonly id: string;\n readonly outline: OutlineCapability;\n readonly row: OutlineRow;\n readonly index: number;\n readonly current: boolean;\n readonly selected: boolean;\n readonly focused: boolean;\n readonly moving: boolean;\n readonly editable: boolean;\n readonly foldable: boolean;\n readonly renaming: boolean;\n readonly mode: 'light' | 'dark';\n readonly untitled: string;\n readonly onClick: (event: ReactMouseEvent) => void;\n readonly onPointerDown: (event: ReactPointerEvent) => void;\n readonly onRenameStart: () => void;\n readonly onRenameEnd: () => void;\n /** The row's menu is about to open: the row becomes the selection. */\n readonly onMenu: () => void;\n}\n\nfunction Row(props: RowProps) {\n const { row, outline } = props;\n const { item, depth, hasChildren, expanded } = row;\n const menuButton = useRef<HTMLSpanElement>(null);\n // An item that goes nowhere and runs nothing is drawn faint: a heading of the outline.\n const inert = !item.target && !item.action;\n const color = readableColor(item.color, props.mode);\n const tone = props.selected\n ? 'bg-accent-light text-fg'\n : props.current\n ? 'bg-hover text-fg'\n : 'text-fg-secondary hover:bg-hover';\n return (\n <div\n id={props.id}\n role=\"treeitem\"\n aria-level={depth + 1}\n aria-expanded={hasChildren ? expanded : undefined}\n aria-selected={props.selected}\n aria-current={props.current ? 'location' : undefined}\n onClick={props.onClick}\n onDoubleClick={() => props.editable && props.onRenameStart()}\n onContextMenu={(event) => {\n if (!props.editable) return;\n event.preventDefault();\n props.onMenu();\n menuButton.current?.querySelector('button')?.click();\n }}\n onPointerDown={props.onPointerDown}\n className={`group absolute inset-x-0 flex cursor-default select-none items-center gap-0.5 rounded pe-1 ${tone} ${\n props.focused ? 'ring-accent/60 ring-1 ring-inset' : ''\n } ${props.moving ? 'opacity-40' : ''}`}\n style={{\n top: props.index * OUTLINE_ROW_HEIGHT,\n height: OUTLINE_ROW_HEIGHT,\n paddingInlineStart: 4 + depth * OUTLINE_INDENT,\n }}\n >\n {props.current && (\n <span aria-hidden className=\"bg-accent absolute inset-y-1 start-0 w-0.5 rounded-full\" />\n )}\n <button\n type=\"button\"\n tabIndex={-1}\n aria-hidden\n disabled={!hasChildren || !props.foldable}\n onClick={(event) => {\n event.stopPropagation();\n if (expanded) outline.collapse(item.ref);\n else outline.expand(item.ref);\n }}\n className=\"text-fg-muted flex h-5 w-5 shrink-0 items-center justify-center rounded disabled:cursor-default\"\n >\n {hasChildren && (\n <Icon\n name=\"chevronRight\"\n size={14}\n className={`transition-transform rtl:-scale-x-100 ${expanded ? 'rotate-90 rtl:-rotate-90' : ''}`}\n />\n )}\n </button>\n {props.renaming ? (\n <RenameField\n title={item.title}\n onDone={(title) => {\n props.onRenameEnd();\n if (title !== null && title !== item.title) {\n void outline.update(item.ref, { title }).catch(() => {});\n }\n }}\n />\n ) : (\n <span\n className={`min-w-0 flex-1 truncate ${inert ? 'opacity-60' : ''}`}\n style={{\n fontSize: TEXT_PX,\n color: color ?? undefined,\n fontWeight: item.bold ? 600 : undefined,\n fontStyle: item.italic ? 'italic' : undefined,\n }}\n title={item.title || props.untitled}\n >\n {item.title || props.untitled}\n </span>\n )}\n {props.editable && !props.renaming && (\n <span\n ref={menuButton}\n onClick={(event) => event.stopPropagation()}\n onPointerDownCapture={props.onMenu}\n className={`shrink-0 ${props.selected || props.focused ? '' : 'opacity-0 focus-within:opacity-100 group-hover:opacity-100'}`}\n >\n <RowMenuButton />\n </span>\n )}\n </div>\n );\n}\n\n/** The row's menu button: the outline's commands for the selected row. */\nfunction RowMenuButton() {\n const more = useCommand('menu:outline-item');\n if (!more.visible) return null;\n return <CommandButton cmd={more} variant=\"icon\" run={() => void more.run()} />;\n}\n\n/**\n * The title being typed in its row: Enter or leaving the field keeps it, Escape keeps the one it\n * had. The field is laid out at 16px and drawn at the row's size, so iOS doesn't zoom in on it.\n */\nfunction RenameField({ title, onDone }: { title: string; onDone: (title: string | null) => void }) {\n const t = useT();\n const field = useRef<HTMLInputElement>(null);\n const done = useRef(false);\n const [draft, setDraft] = useState(title);\n useLayoutEffect(() => {\n field.current?.focus();\n field.current?.select();\n }, []);\n const finish = (value: string | null) => {\n if (done.current) return;\n done.current = true;\n onDone(value);\n };\n const scale = TEXT_PX / FIELD_PX;\n return (\n <span className=\"relative min-w-0 flex-1\" style={{ height: OUTLINE_ROW_HEIGHT - 6 }}>\n <input\n ref={field}\n type=\"text\"\n value={draft}\n aria-label={t('commands.outline.rename')}\n maxLength={32_767}\n onChange={(event) => setDraft(event.target.value)}\n onKeyDown={(event) => {\n event.stopPropagation();\n if (event.key === 'Enter') finish(draft);\n else if (event.key === 'Escape') finish(null);\n }}\n onBlur={() => finish(draft)}\n onClick={(event) => event.stopPropagation()}\n className=\"border-accent bg-surface text-fg absolute start-0 top-0 origin-top-left rounded border px-1 outline-none rtl:origin-top-right\"\n style={{\n fontSize: FIELD_PX,\n width: `${100 / scale}%`,\n height: `${100 / scale}%`,\n transform: `scale(${scale})`,\n }}\n />\n </span>\n );\n}\n","/**\n * The outline panel: the document's outline (its bookmarks) as a tree. A row goes where its item\n * goes; the row of the item the main view is reading is marked, and comes into view as the\n * reader moves on. A filter finds items by their title, in their place. A session that may change\n * the outline adds items (after the selected one, at the place in view, renaming them at once),\n * renames, drags and deletes them, and opens a row's menu for the rest.\n */\nimport { useCommand } from '@embedpdf/react/commands';\nimport { useT } from '@embedpdf/react/i18n';\nimport {\n useOutline,\n useOutlineState,\n type OutlineItem,\n type OutlineItemRef,\n} from '@embedpdf/react/outline';\nimport { useSurface } from '@embedpdf/react/shell';\nimport { useEffect, useMemo, useState } from 'react';\n\nimport { Icon } from './icons';\nimport { OutlineRows } from './outline-rows';\nimport { filteredRows, outlineKeyOf } from './outline-tree';\nimport { useCloseOnPick } from './panel-frame';\nimport { useTheme } from './theme';\nimport { CommandButton } from './toolbar';\nimport { OUTLINE_RENAME } from '../config/outline';\n\n/** The rename request's props: an item to rename, or the selection an add is about to replace. */\ntype RenameRequest = { readonly item?: number; readonly after?: number | null };\n\n/**\n * The row to mark for where the reader is: the current item's own when it shows, else that of\n * the nearest item it sits under that does.\n */\nfunction shownKeyOf(\n current: OutlineItemRef | null,\n shown: ReadonlySet<string>,\n items: readonly OutlineItem[],\n): string | null {\n if (!current) return null;\n const byKey = new Map(items.map((item) => [outlineKeyOf(item.ref), item]));\n for (let key: string | null = outlineKeyOf(current); key !== null; ) {\n if (shown.has(key)) return key;\n const parent: OutlineItemRef | null = byKey.get(key)?.parent ?? null;\n key = parent ? outlineKeyOf(parent) : null;\n }\n return null;\n}\n\nexport function OutlinePanel() {\n const t = useT();\n const outline = useOutline();\n const { items, rows, current, selected, status, incomplete } = useOutlineState();\n const { mode } = useTheme();\n const closeOnPick = useCloseOnPick();\n const add = useCommand('outline:add');\n const expandAll = useCommand('outline:expand-all');\n const collapseAll = useCommand('outline:collapse-all');\n const editable = add.visible && add.enabled;\n const [filter, setFilter] = useState('');\n const [renamingKey, setRenamingKey] = useState<string | null>(null);\n\n const filtering = filter.trim() !== '';\n const shownRows = useMemo(\n () => (filtering ? filteredRows(items, filter) : rows),\n [filtering, items, filter, rows],\n );\n const shownKeys = useMemo(\n () => new Set(shownRows.map((row) => outlineKeyOf(row.item.ref))),\n [shownRows],\n );\n const currentKey = shownKeyOf(current, shownKeys, items);\n\n // A rename asked for by a command: the item it names, or the one an add selects.\n const renameRequest = useSurface(OUTLINE_RENAME);\n useEffect(() => {\n if (!renameRequest.isOpen) return;\n const request = renameRequest.props as RenameRequest;\n if (request.item !== undefined) {\n setRenamingKey(String(request.item));\n renameRequest.close();\n return;\n }\n const [first] = selected;\n if (!first || first.objectNumber === request.after) return;\n setFilter('');\n setRenamingKey(outlineKeyOf(first));\n renameRequest.close();\n }, [renameRequest, selected]);\n\n const toolbar = (\n <div className=\"border-border-subtle flex items-center gap-1 border-b p-2\">\n <div className=\"relative min-w-0 flex-1\">\n <div className=\"text-fg-muted pointer-events-none absolute inset-y-0 start-0 flex items-center ps-2\">\n <Icon name=\"search\" size={14} />\n </div>\n <input\n type=\"search\"\n value={filter}\n placeholder={t('outline.filter')}\n aria-label={t('outline.filter')}\n onChange={(event) => setFilter(event.target.value)}\n className=\"border-border bg-surface text-fg focus:border-accent focus:ring-accent w-full rounded-md border py-1 pe-2 ps-7 text-sm outline-none focus:ring-1\"\n />\n </div>\n {add.visible && <CommandButton cmd={add} variant=\"icon\" run={() => void add.run()} />}\n {expandAll.visible && (\n <CommandButton cmd={expandAll} variant=\"icon\" run={() => void expandAll.run()} />\n )}\n {collapseAll.visible && (\n <CommandButton cmd={collapseAll} variant=\"icon\" run={() => void collapseAll.run()} />\n )}\n </div>\n );\n\n const message = (text: string, withAdd = false) => (\n <div className=\"text-fg-muted flex flex-col items-center gap-3 p-6 text-center text-sm\">\n <p>{text}</p>\n {withAdd && editable && (\n <button\n type=\"button\"\n onClick={() => void add.run()}\n className=\"border-border text-fg hover:bg-hover rounded-md border px-3 py-1.5 text-sm\"\n >\n {add.label}\n </button>\n )}\n </div>\n );\n\n const body = (() => {\n if (items.length === 0) {\n if (status === 'idle' || status === 'loading') return message(t('outline.loading'));\n if (status === 'forbidden' || status === 'error') return message(t('outline.failed'));\n return message(t('outline.empty'), true);\n }\n if (filtering && shownRows.length === 0) return message(t('outline.noMatches'));\n return (\n <OutlineRows\n outline={outline}\n rows={shownRows}\n currentKey={currentKey}\n selected={selected}\n editable={editable}\n filtering={filtering}\n renamingKey={renamingKey}\n onRename={setRenamingKey}\n mode={mode}\n onPicked={closeOnPick}\n label={t('panels.outline')}\n />\n );\n })();\n\n return (\n <div className=\"flex min-h-0 flex-1 flex-col\">\n {toolbar}\n {incomplete && (\n <p className=\"text-fg-muted border-border-subtle border-b px-3 py-2 text-xs\">\n {t('outline.incomplete')}\n </p>\n )}\n {body}\n </div>\n );\n}\n"],"mappings":"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"}
@@ -0,0 +1,330 @@
1
+ import { p as OUTLINE_PROPERTIES_DIALOG } from "./commands-BkgLP3Om.js";
2
+ import { t as Dialog } from "./dialog-BIb373cg.js";
3
+ import { useId, useState } from "react";
4
+ import { useKernel, useOptionalCapability } from "@embedpdf/react/runtime";
5
+ import { OutlineToken } from "@embedpdf/react/outline";
6
+ import { useT } from "@embedpdf/react/i18n";
7
+ import { useSurface } from "@embedpdf/react/shell";
8
+ import { jsx, jsxs } from "react/jsx-runtime";
9
+ //#region src/ui/outline-properties.tsx
10
+ /**
11
+ * An outline item's properties, which `outline:properties` opens for the selected item: its
12
+ * title, the colour and style it is drawn in, whether it is open when the document opens, and
13
+ * where it goes. Save writes what changed as one change; Escape or Cancel keeps the item as it
14
+ * was. A target the viewer doesn't write (a script, another file, an app) shows, and stays.
15
+ */
16
+ /** The colours offered for a title, after "none": the viewer's own text colour. */
17
+ const SWATCHES = [
18
+ "#000000",
19
+ "#c92a2a",
20
+ "#e8590c",
21
+ "#2b8a3e",
22
+ "#1864ab",
23
+ "#6741d9",
24
+ "#868e96"
25
+ ];
26
+ /** The standard page verbs a target can name. */
27
+ const PAGE_VERBS = [
28
+ "NextPage",
29
+ "PrevPage",
30
+ "FirstPage",
31
+ "LastPage"
32
+ ];
33
+ const PAGE_VERB_KEYS = {
34
+ NextPage: "commands.page.next",
35
+ PrevPage: "commands.page.previous",
36
+ FirstPage: "commands.page.first",
37
+ LastPage: "commands.page.last"
38
+ };
39
+ function OutlinePropertiesDialog() {
40
+ const surface = useSurface(OUTLINE_PROPERTIES_DIALOG);
41
+ const outline = useOptionalCapability(OutlineToken);
42
+ const number = surface.props.item;
43
+ const item = outline && number !== void 0 ? outline.get({
44
+ kind: "objectNumber",
45
+ objectNumber: number
46
+ }) : null;
47
+ if (!surface.isOpen || !outline || !item) return null;
48
+ return /* @__PURE__ */ jsx(PropertiesForm, {
49
+ outline,
50
+ item,
51
+ hasChildren: outline.getChildren(item.ref).length > 0,
52
+ onClose: surface.close
53
+ }, number);
54
+ }
55
+ function PropertiesForm({ outline, item, hasChildren, onClose }) {
56
+ const t = useT();
57
+ const kernel = useKernel();
58
+ const titleId = useId();
59
+ const target = item.target;
60
+ const pageIndexOf = (page) => kernel.documents.getPage(page)?.index ?? 0;
61
+ const [title, setTitle] = useState(item.title);
62
+ const [color, setColor] = useState(item.color);
63
+ const [bold, setBold] = useState(item.bold);
64
+ const [italic, setItalic] = useState(item.italic);
65
+ const [open, setOpen] = useState(item.open);
66
+ const [choice, setChoice] = useState(() => {
67
+ if (!target) return "none";
68
+ if (target.kind === "goto") return "page";
69
+ if (target.kind === "uri") return "uri";
70
+ if (target.kind === "named" && PAGE_VERBS.includes(target.name)) return "named";
71
+ return "kept";
72
+ });
73
+ const [page, setPage] = useState(() => String(target?.kind === "goto" ? pageIndexOf(target.destination.page) + 1 : 1));
74
+ const initialFit = target?.kind === "goto" && (target.destination.kind === "fit" || target.destination.kind === "fitH") ? target.destination.kind : "kept";
75
+ const [fit, setFit] = useState(initialFit);
76
+ const [uri, setUri] = useState(target?.kind === "uri" ? target.uri : "");
77
+ const [verb, setVerb] = useState(target?.kind === "named" && PAGE_VERBS.includes(target.name) ? target.name : "NextPage");
78
+ /** The target the form says, or `undefined` to leave the item's as it is. */
79
+ const targetOf = () => {
80
+ switch (choice) {
81
+ case "none": return target ? null : void 0;
82
+ case "view": return outline.getCurrentViewTarget() ?? void 0;
83
+ case "page": {
84
+ const pageInfo = kernel.documents.getPage(Math.max(0, Number(page) - 1));
85
+ if (!pageInfo) return void 0;
86
+ if (target?.kind === "goto" && pageIndexOf(target.destination.page) === pageInfo.index && fit === initialFit) return;
87
+ return {
88
+ kind: "goto",
89
+ destination: fit === "fitH" ? {
90
+ kind: "fitH",
91
+ page: pageInfo.ref,
92
+ y: 0
93
+ } : {
94
+ kind: "fit",
95
+ page: pageInfo.ref
96
+ }
97
+ };
98
+ }
99
+ case "uri": {
100
+ const trimmed = uri.trim();
101
+ if (!trimmed || target?.kind === "uri" && target.uri === trimmed) return void 0;
102
+ return {
103
+ kind: "uri",
104
+ uri: trimmed
105
+ };
106
+ }
107
+ case "named": return target?.kind === "named" && target.name === verb ? void 0 : {
108
+ kind: "named",
109
+ name: verb
110
+ };
111
+ case "kept": return;
112
+ }
113
+ };
114
+ const save = () => {
115
+ const patch = {
116
+ ...title !== item.title ? { title } : {},
117
+ ...color !== item.color ? { color } : {},
118
+ ...bold !== item.bold ? { bold } : {},
119
+ ...italic !== item.italic ? { italic } : {},
120
+ ...hasChildren && open !== item.open ? { open } : {}
121
+ };
122
+ const nextTarget = targetOf();
123
+ if (nextTarget !== void 0) patch.target = nextTarget;
124
+ if (Object.keys(patch).length > 0) outline.update(item.ref, patch).catch(() => {});
125
+ onClose();
126
+ };
127
+ const field = "border-border bg-surface text-fg focus:border-accent w-full rounded border px-2.5 py-1.5 text-sm outline-none";
128
+ const label = "text-fg-secondary mb-1 block text-xs font-medium";
129
+ const check = "text-fg-secondary flex items-center gap-2 text-sm";
130
+ return /* @__PURE__ */ jsx(Dialog, {
131
+ labelledBy: titleId,
132
+ onClose,
133
+ className: "border-border bg-surface w-96 max-w-[calc(100vw-2rem)] rounded-lg border p-4 shadow-xl",
134
+ children: /* @__PURE__ */ jsxs("form", {
135
+ onSubmit: (event) => {
136
+ event.preventDefault();
137
+ save();
138
+ },
139
+ className: "flex flex-col gap-3",
140
+ children: [
141
+ /* @__PURE__ */ jsx("h2", {
142
+ id: titleId,
143
+ className: "text-fg text-base font-semibold",
144
+ children: t("outline.properties.title")
145
+ }),
146
+ /* @__PURE__ */ jsxs("label", { children: [/* @__PURE__ */ jsx("span", {
147
+ className: label,
148
+ children: t("outline.properties.name")
149
+ }), /* @__PURE__ */ jsx("input", {
150
+ type: "text",
151
+ value: title,
152
+ maxLength: 32767,
153
+ onChange: (event) => setTitle(event.target.value),
154
+ className: field
155
+ })] }),
156
+ /* @__PURE__ */ jsxs("fieldset", { children: [/* @__PURE__ */ jsx("legend", {
157
+ className: label,
158
+ children: t("outline.properties.color")
159
+ }), /* @__PURE__ */ jsxs("div", {
160
+ className: "flex flex-wrap items-center gap-1.5",
161
+ children: [
162
+ /* @__PURE__ */ jsx("button", {
163
+ type: "button",
164
+ "aria-pressed": color === null,
165
+ onClick: () => setColor(null),
166
+ className: `border-border text-fg rounded border px-2 py-0.5 text-xs ${color === null ? "ring-accent ring-2" : ""}`,
167
+ children: t("outline.properties.noColor")
168
+ }),
169
+ SWATCHES.map((swatch) => /* @__PURE__ */ jsx("button", {
170
+ type: "button",
171
+ "aria-label": swatch,
172
+ "aria-pressed": color === swatch,
173
+ onClick: () => setColor(swatch),
174
+ className: `border-border h-6 w-6 rounded-full border ${color === swatch ? "ring-accent ring-2 ring-offset-1" : ""}`,
175
+ style: { background: swatch }
176
+ }, swatch)),
177
+ /* @__PURE__ */ jsx("input", {
178
+ type: "color",
179
+ "aria-label": t("outline.properties.customColor"),
180
+ value: color ?? "#000000",
181
+ onChange: (event) => setColor(event.target.value),
182
+ className: "h-6 w-8 cursor-pointer rounded border-0 bg-transparent p-0"
183
+ })
184
+ ]
185
+ })] }),
186
+ /* @__PURE__ */ jsxs("div", {
187
+ className: "flex gap-4",
188
+ children: [/* @__PURE__ */ jsxs("label", {
189
+ className: check,
190
+ children: [/* @__PURE__ */ jsx("input", {
191
+ type: "checkbox",
192
+ checked: bold,
193
+ onChange: (event) => setBold(event.target.checked)
194
+ }), /* @__PURE__ */ jsx("span", {
195
+ className: "font-semibold",
196
+ children: t("outline.properties.bold")
197
+ })]
198
+ }), /* @__PURE__ */ jsxs("label", {
199
+ className: check,
200
+ children: [/* @__PURE__ */ jsx("input", {
201
+ type: "checkbox",
202
+ checked: italic,
203
+ onChange: (event) => setItalic(event.target.checked)
204
+ }), /* @__PURE__ */ jsx("span", {
205
+ className: "italic",
206
+ children: t("outline.properties.italic")
207
+ })]
208
+ })]
209
+ }),
210
+ /* @__PURE__ */ jsxs("label", {
211
+ className: `${check} ${hasChildren ? "" : "opacity-50"}`,
212
+ children: [/* @__PURE__ */ jsx("input", {
213
+ type: "checkbox",
214
+ disabled: !hasChildren,
215
+ checked: hasChildren && open,
216
+ onChange: (event) => setOpen(event.target.checked)
217
+ }), t("outline.properties.open")]
218
+ }),
219
+ /* @__PURE__ */ jsxs("fieldset", {
220
+ className: "flex flex-col gap-2",
221
+ children: [
222
+ /* @__PURE__ */ jsx("legend", {
223
+ className: label,
224
+ children: t("outline.properties.target")
225
+ }),
226
+ /* @__PURE__ */ jsxs("select", {
227
+ value: choice,
228
+ onChange: (event) => setChoice(event.target.value),
229
+ className: field,
230
+ children: [
231
+ /* @__PURE__ */ jsx("option", {
232
+ value: "none",
233
+ children: t("outline.properties.targetNone")
234
+ }),
235
+ /* @__PURE__ */ jsx("option", {
236
+ value: "view",
237
+ children: t("outline.properties.targetView")
238
+ }),
239
+ /* @__PURE__ */ jsx("option", {
240
+ value: "page",
241
+ children: t("linkEditor.page")
242
+ }),
243
+ /* @__PURE__ */ jsx("option", {
244
+ value: "uri",
245
+ children: t("linkEditor.url")
246
+ }),
247
+ /* @__PURE__ */ jsx("option", {
248
+ value: "named",
249
+ children: t("outline.properties.targetNamed")
250
+ }),
251
+ choice === "kept" && /* @__PURE__ */ jsx("option", {
252
+ value: "kept",
253
+ children: t("outline.properties.targetKept")
254
+ })
255
+ ]
256
+ }),
257
+ choice === "page" && /* @__PURE__ */ jsxs("div", {
258
+ className: "flex gap-2",
259
+ children: [/* @__PURE__ */ jsx("input", {
260
+ type: "number",
261
+ min: 1,
262
+ value: page,
263
+ "aria-label": t("linkEditor.pagePlaceholder"),
264
+ onChange: (event) => setPage(event.target.value),
265
+ className: `${field} w-24`
266
+ }), /* @__PURE__ */ jsxs("select", {
267
+ value: fit,
268
+ "aria-label": t("outline.properties.fit"),
269
+ onChange: (event) => setFit(event.target.value),
270
+ className: field,
271
+ children: [
272
+ initialFit === "kept" && /* @__PURE__ */ jsx("option", {
273
+ value: "kept",
274
+ children: t("outline.properties.fitKept")
275
+ }),
276
+ /* @__PURE__ */ jsx("option", {
277
+ value: "fit",
278
+ children: t("commands.zoom.fitPage")
279
+ }),
280
+ /* @__PURE__ */ jsx("option", {
281
+ value: "fitH",
282
+ children: t("commands.zoom.fitWidth")
283
+ })
284
+ ]
285
+ })]
286
+ }),
287
+ choice === "uri" && /* @__PURE__ */ jsx("input", {
288
+ type: "url",
289
+ value: uri,
290
+ placeholder: t("linkEditor.urlPlaceholder"),
291
+ onChange: (event) => setUri(event.target.value),
292
+ className: field
293
+ }),
294
+ choice === "named" && /* @__PURE__ */ jsx("select", {
295
+ value: verb,
296
+ "aria-label": t("outline.properties.targetNamed"),
297
+ onChange: (event) => setVerb(event.target.value),
298
+ className: field,
299
+ children: PAGE_VERBS.map((name) => /* @__PURE__ */ jsx("option", {
300
+ value: name,
301
+ children: t(PAGE_VERB_KEYS[name])
302
+ }, name))
303
+ }),
304
+ choice === "kept" && /* @__PURE__ */ jsx("p", {
305
+ className: "text-fg-muted text-xs",
306
+ children: t("outline.properties.keptNote")
307
+ })
308
+ ]
309
+ }),
310
+ /* @__PURE__ */ jsxs("div", {
311
+ className: "mt-1 flex justify-end gap-2",
312
+ children: [/* @__PURE__ */ jsx("button", {
313
+ type: "button",
314
+ onClick: onClose,
315
+ className: "border-border text-fg hover:bg-hover rounded border px-3 py-1.5 text-sm",
316
+ children: t("outline.properties.cancel")
317
+ }), /* @__PURE__ */ jsx("button", {
318
+ type: "submit",
319
+ className: "bg-accent text-on-accent rounded px-3 py-1.5 text-sm font-medium",
320
+ children: t("outline.properties.save")
321
+ })]
322
+ })
323
+ ]
324
+ })
325
+ });
326
+ }
327
+ //#endregion
328
+ export { OutlinePropertiesDialog };
329
+
330
+ //# sourceMappingURL=outline-properties-BCa2cc0t.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"outline-properties-BCa2cc0t.js","names":[],"sources":["../src/ui/outline-properties.tsx"],"sourcesContent":["/**\n * An outline item's properties, which `outline:properties` opens for the selected item: its\n * title, the colour and style it is drawn in, whether it is open when the document opens, and\n * where it goes. Save writes what changed as one change; Escape or Cancel keeps the item as it\n * was. A target the viewer doesn't write (a script, another file, an app) shows, and stays.\n */\nimport { useT } from '@embedpdf/react/i18n';\nimport {\n OutlineToken,\n type OutlineCapability,\n type OutlineItem,\n type OutlineItemPatch,\n} from '@embedpdf/react/outline';\nimport { useKernel, useOptionalCapability } from '@embedpdf/react/runtime';\nimport { useSurface } from '@embedpdf/react/shell';\nimport { useId, useState } from 'react';\n\nimport { Dialog } from './dialog';\nimport { OUTLINE_PROPERTIES_DIALOG } from '../config/outline';\n\n/** The colours offered for a title, after \"none\": the viewer's own text colour. */\nconst SWATCHES = ['#000000', '#c92a2a', '#e8590c', '#2b8a3e', '#1864ab', '#6741d9', '#868e96'];\n\n/** The standard page verbs a target can name. */\nconst PAGE_VERBS = ['NextPage', 'PrevPage', 'FirstPage', 'LastPage'] as const;\ntype PageVerb = (typeof PAGE_VERBS)[number];\nconst PAGE_VERB_KEYS: Record<PageVerb, string> = {\n NextPage: 'commands.page.next',\n PrevPage: 'commands.page.previous',\n FirstPage: 'commands.page.first',\n LastPage: 'commands.page.last',\n};\n\ntype TargetChoice = 'none' | 'view' | 'page' | 'uri' | 'named' | 'kept';\ntype Fit = 'fit' | 'fitH' | 'kept';\n\nexport function OutlinePropertiesDialog() {\n const surface = useSurface(OUTLINE_PROPERTIES_DIALOG);\n const outline = useOptionalCapability(OutlineToken);\n const number = (surface.props as { item?: number }).item;\n const item =\n outline && number !== undefined\n ? outline.get({ kind: 'objectNumber', objectNumber: number })\n : null;\n if (!surface.isOpen || !outline || !item) return null;\n return (\n <PropertiesForm\n key={number}\n outline={outline}\n item={item}\n hasChildren={outline.getChildren(item.ref).length > 0}\n onClose={surface.close}\n />\n );\n}\n\nfunction PropertiesForm({\n outline,\n item,\n hasChildren,\n onClose,\n}: {\n outline: OutlineCapability;\n item: OutlineItem;\n hasChildren: boolean;\n onClose: () => void;\n}) {\n const t = useT();\n const kernel = useKernel();\n const titleId = useId();\n const target = item.target;\n const pageIndexOf = (page: { kind: 'objectNumber'; objectNumber: number }) =>\n kernel.documents.getPage(page)?.index ?? 0;\n\n const [title, setTitle] = useState(item.title);\n const [color, setColor] = useState<string | null>(item.color);\n const [bold, setBold] = useState(item.bold);\n const [italic, setItalic] = useState(item.italic);\n const [open, setOpen] = useState(item.open);\n const [choice, setChoice] = useState<TargetChoice>(() => {\n if (!target) return 'none';\n if (target.kind === 'goto') return 'page';\n if (target.kind === 'uri') return 'uri';\n if (target.kind === 'named' && (PAGE_VERBS as readonly string[]).includes(target.name)) {\n return 'named';\n }\n return 'kept';\n });\n const [page, setPage] = useState(() =>\n String(target?.kind === 'goto' ? pageIndexOf(target.destination.page) + 1 : 1),\n );\n // A destination that is neither of the two fits (a spot on the page) is offered as it is.\n const initialFit: Fit =\n target?.kind === 'goto' &&\n (target.destination.kind === 'fit' || target.destination.kind === 'fitH')\n ? target.destination.kind\n : 'kept';\n const [fit, setFit] = useState<Fit>(initialFit);\n const [uri, setUri] = useState(target?.kind === 'uri' ? target.uri : '');\n const [verb, setVerb] = useState<PageVerb>(\n target?.kind === 'named' && (PAGE_VERBS as readonly string[]).includes(target.name)\n ? (target.name as PageVerb)\n : 'NextPage',\n );\n\n /** The target the form says, or `undefined` to leave the item's as it is. */\n const targetOf = (): OutlineItemPatch['target'] | undefined => {\n switch (choice) {\n case 'none':\n return target ? null : undefined;\n case 'view':\n return outline.getCurrentViewTarget() ?? undefined;\n case 'page': {\n const pageInfo = kernel.documents.getPage(Math.max(0, Number(page) - 1));\n if (!pageInfo) return undefined;\n // The page and fit the item already has keep the exact spot it goes to.\n if (\n target?.kind === 'goto' &&\n pageIndexOf(target.destination.page) === pageInfo.index &&\n fit === initialFit\n ) {\n return undefined;\n }\n return {\n kind: 'goto',\n destination:\n fit === 'fitH'\n ? { kind: 'fitH', page: pageInfo.ref, y: 0 }\n : { kind: 'fit', page: pageInfo.ref },\n };\n }\n case 'uri': {\n const trimmed = uri.trim();\n if (!trimmed || (target?.kind === 'uri' && target.uri === trimmed)) return undefined;\n return { kind: 'uri', uri: trimmed };\n }\n case 'named':\n return target?.kind === 'named' && target.name === verb\n ? undefined\n : { kind: 'named', name: verb };\n case 'kept':\n return undefined;\n }\n };\n\n const save = () => {\n const patch: OutlineItemPatch = {\n ...(title !== item.title ? { title } : {}),\n ...(color !== item.color ? { color } : {}),\n ...(bold !== item.bold ? { bold } : {}),\n ...(italic !== item.italic ? { italic } : {}),\n ...(hasChildren && open !== item.open ? { open } : {}),\n };\n const nextTarget = targetOf();\n if (nextTarget !== undefined) patch.target = nextTarget;\n if (Object.keys(patch).length > 0) void outline.update(item.ref, patch).catch(() => {});\n onClose();\n };\n\n const field =\n 'border-border bg-surface text-fg focus:border-accent w-full rounded border px-2.5 py-1.5 text-sm outline-none';\n const label = 'text-fg-secondary mb-1 block text-xs font-medium';\n const check = 'text-fg-secondary flex items-center gap-2 text-sm';\n\n return (\n <Dialog\n labelledBy={titleId}\n onClose={onClose}\n className=\"border-border bg-surface w-96 max-w-[calc(100vw-2rem)] rounded-lg border p-4 shadow-xl\"\n >\n <form\n onSubmit={(event) => {\n event.preventDefault();\n save();\n }}\n className=\"flex flex-col gap-3\"\n >\n <h2 id={titleId} className=\"text-fg text-base font-semibold\">\n {t('outline.properties.title')}\n </h2>\n\n <label>\n <span className={label}>{t('outline.properties.name')}</span>\n <input\n type=\"text\"\n value={title}\n maxLength={32_767}\n onChange={(event) => setTitle(event.target.value)}\n className={field}\n />\n </label>\n\n <fieldset>\n <legend className={label}>{t('outline.properties.color')}</legend>\n <div className=\"flex flex-wrap items-center gap-1.5\">\n <button\n type=\"button\"\n aria-pressed={color === null}\n onClick={() => setColor(null)}\n className={`border-border text-fg rounded border px-2 py-0.5 text-xs ${\n color === null ? 'ring-accent ring-2' : ''\n }`}\n >\n {t('outline.properties.noColor')}\n </button>\n {SWATCHES.map((swatch) => (\n <button\n key={swatch}\n type=\"button\"\n aria-label={swatch}\n aria-pressed={color === swatch}\n onClick={() => setColor(swatch)}\n className={`border-border h-6 w-6 rounded-full border ${\n color === swatch ? 'ring-accent ring-2 ring-offset-1' : ''\n }`}\n style={{ background: swatch }}\n />\n ))}\n <input\n type=\"color\"\n aria-label={t('outline.properties.customColor')}\n value={color ?? '#000000'}\n onChange={(event) => setColor(event.target.value)}\n className=\"h-6 w-8 cursor-pointer rounded border-0 bg-transparent p-0\"\n />\n </div>\n </fieldset>\n\n <div className=\"flex gap-4\">\n <label className={check}>\n <input\n type=\"checkbox\"\n checked={bold}\n onChange={(event) => setBold(event.target.checked)}\n />\n <span className=\"font-semibold\">{t('outline.properties.bold')}</span>\n </label>\n <label className={check}>\n <input\n type=\"checkbox\"\n checked={italic}\n onChange={(event) => setItalic(event.target.checked)}\n />\n <span className=\"italic\">{t('outline.properties.italic')}</span>\n </label>\n </div>\n\n <label className={`${check} ${hasChildren ? '' : 'opacity-50'}`}>\n <input\n type=\"checkbox\"\n disabled={!hasChildren}\n checked={hasChildren && open}\n onChange={(event) => setOpen(event.target.checked)}\n />\n {t('outline.properties.open')}\n </label>\n\n <fieldset className=\"flex flex-col gap-2\">\n <legend className={label}>{t('outline.properties.target')}</legend>\n <select\n value={choice}\n onChange={(event) => setChoice(event.target.value as TargetChoice)}\n className={field}\n >\n <option value=\"none\">{t('outline.properties.targetNone')}</option>\n <option value=\"view\">{t('outline.properties.targetView')}</option>\n <option value=\"page\">{t('linkEditor.page')}</option>\n <option value=\"uri\">{t('linkEditor.url')}</option>\n <option value=\"named\">{t('outline.properties.targetNamed')}</option>\n {choice === 'kept' && (\n <option value=\"kept\">{t('outline.properties.targetKept')}</option>\n )}\n </select>\n {choice === 'page' && (\n <div className=\"flex gap-2\">\n <input\n type=\"number\"\n min={1}\n value={page}\n aria-label={t('linkEditor.pagePlaceholder')}\n onChange={(event) => setPage(event.target.value)}\n className={`${field} w-24`}\n />\n <select\n value={fit}\n aria-label={t('outline.properties.fit')}\n onChange={(event) => setFit(event.target.value as Fit)}\n className={field}\n >\n {initialFit === 'kept' && (\n <option value=\"kept\">{t('outline.properties.fitKept')}</option>\n )}\n <option value=\"fit\">{t('commands.zoom.fitPage')}</option>\n <option value=\"fitH\">{t('commands.zoom.fitWidth')}</option>\n </select>\n </div>\n )}\n {choice === 'uri' && (\n <input\n type=\"url\"\n value={uri}\n placeholder={t('linkEditor.urlPlaceholder')}\n onChange={(event) => setUri(event.target.value)}\n className={field}\n />\n )}\n {choice === 'named' && (\n <select\n value={verb}\n aria-label={t('outline.properties.targetNamed')}\n onChange={(event) => setVerb(event.target.value as PageVerb)}\n className={field}\n >\n {PAGE_VERBS.map((name) => (\n <option key={name} value={name}>\n {t(PAGE_VERB_KEYS[name])}\n </option>\n ))}\n </select>\n )}\n {choice === 'kept' && (\n <p className=\"text-fg-muted text-xs\">{t('outline.properties.keptNote')}</p>\n )}\n </fieldset>\n\n <div className=\"mt-1 flex justify-end gap-2\">\n <button\n type=\"button\"\n onClick={onClose}\n className=\"border-border text-fg hover:bg-hover rounded border px-3 py-1.5 text-sm\"\n >\n {t('outline.properties.cancel')}\n </button>\n <button\n type=\"submit\"\n className=\"bg-accent text-on-accent rounded px-3 py-1.5 text-sm font-medium\"\n >\n {t('outline.properties.save')}\n </button>\n </div>\n </form>\n </Dialog>\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAqBA,MAAM,WAAW;CAAC;CAAW;CAAW;CAAW;CAAW;CAAW;CAAW;AAAS;;AAG7F,MAAM,aAAa;CAAC;CAAY;CAAY;CAAa;AAAU;AAEnE,MAAM,iBAA2C;CAC/C,UAAU;CACV,UAAU;CACV,WAAW;CACX,UAAU;AACZ;AAKA,SAAgB,0BAA0B;CACxC,MAAM,UAAU,WAAW,yBAAyB;CACpD,MAAM,UAAU,sBAAsB,YAAY;CAClD,MAAM,SAAU,QAAQ,MAA4B;CACpD,MAAM,OACJ,WAAW,WAAW,KAAA,IAClB,QAAQ,IAAI;EAAE,MAAM;EAAgB,cAAc;CAAO,CAAC,IAC1D;CACN,IAAI,CAAC,QAAQ,UAAU,CAAC,WAAW,CAAC,MAAM,OAAO;CACjD,OACE,oBAAC,gBAAD;EAEW;EACH;EACN,aAAa,QAAQ,YAAY,KAAK,GAAG,CAAC,CAAC,SAAS;EACpD,SAAS,QAAQ;CAClB,GALM,MAKN;AAEL;AAEA,SAAS,eAAe,EACtB,SACA,MACA,aACA,WAMC;CACD,MAAM,IAAI,KAAK;CACf,MAAM,SAAS,UAAU;CACzB,MAAM,UAAU,MAAM;CACtB,MAAM,SAAS,KAAK;CACpB,MAAM,eAAe,SACnB,OAAO,UAAU,QAAQ,IAAI,CAAC,EAAE,SAAS;CAE3C,MAAM,CAAC,OAAO,YAAY,SAAS,KAAK,KAAK;CAC7C,MAAM,CAAC,OAAO,YAAY,SAAwB,KAAK,KAAK;CAC5D,MAAM,CAAC,MAAM,WAAW,SAAS,KAAK,IAAI;CAC1C,MAAM,CAAC,QAAQ,aAAa,SAAS,KAAK,MAAM;CAChD,MAAM,CAAC,MAAM,WAAW,SAAS,KAAK,IAAI;CAC1C,MAAM,CAAC,QAAQ,aAAa,eAA6B;EACvD,IAAI,CAAC,QAAQ,OAAO;EACpB,IAAI,OAAO,SAAS,QAAQ,OAAO;EACnC,IAAI,OAAO,SAAS,OAAO,OAAO;EAClC,IAAI,OAAO,SAAS,WAAY,WAAiC,SAAS,OAAO,IAAI,GACnF,OAAO;EAET,OAAO;CACT,CAAC;CACD,MAAM,CAAC,MAAM,WAAW,eACtB,OAAO,QAAQ,SAAS,SAAS,YAAY,OAAO,YAAY,IAAI,IAAI,IAAI,CAAC,CAC/E;CAEA,MAAM,aACJ,QAAQ,SAAS,WAChB,OAAO,YAAY,SAAS,SAAS,OAAO,YAAY,SAAS,UAC9D,OAAO,YAAY,OACnB;CACN,MAAM,CAAC,KAAK,UAAU,SAAc,UAAU;CAC9C,MAAM,CAAC,KAAK,UAAU,SAAS,QAAQ,SAAS,QAAQ,OAAO,MAAM,EAAE;CACvE,MAAM,CAAC,MAAM,WAAW,SACtB,QAAQ,SAAS,WAAY,WAAiC,SAAS,OAAO,IAAI,IAC7E,OAAO,OACR,UACN;;CAGA,MAAM,iBAAyD;EAC7D,QAAQ,QAAR;GACE,KAAK,QACH,OAAO,SAAS,OAAO,KAAA;GACzB,KAAK,QACH,OAAO,QAAQ,qBAAqB,KAAK,KAAA;GAC3C,KAAK,QAAQ;IACX,MAAM,WAAW,OAAO,UAAU,QAAQ,KAAK,IAAI,GAAG,OAAO,IAAI,IAAI,CAAC,CAAC;IACvE,IAAI,CAAC,UAAU,OAAO,KAAA;IAEtB,IACE,QAAQ,SAAS,UACjB,YAAY,OAAO,YAAY,IAAI,MAAM,SAAS,SAClD,QAAQ,YAER;IAEF,OAAO;KACL,MAAM;KACN,aACE,QAAQ,SACJ;MAAE,MAAM;MAAQ,MAAM,SAAS;MAAK,GAAG;KAAE,IACzC;MAAE,MAAM;MAAO,MAAM,SAAS;KAAI;IAC1C;GACF;GACA,KAAK,OAAO;IACV,MAAM,UAAU,IAAI,KAAK;IACzB,IAAI,CAAC,WAAY,QAAQ,SAAS,SAAS,OAAO,QAAQ,SAAU,OAAO,KAAA;IAC3E,OAAO;KAAE,MAAM;KAAO,KAAK;IAAQ;GACrC;GACA,KAAK,SACH,OAAO,QAAQ,SAAS,WAAW,OAAO,SAAS,OAC/C,KAAA,IACA;IAAE,MAAM;IAAS,MAAM;GAAK;GAClC,KAAK,QACH;EACJ;CACF;CAEA,MAAM,aAAa;EACjB,MAAM,QAA0B;GAC9B,GAAI,UAAU,KAAK,QAAQ,EAAE,MAAM,IAAI,CAAC;GACxC,GAAI,UAAU,KAAK,QAAQ,EAAE,MAAM,IAAI,CAAC;GACxC,GAAI,SAAS,KAAK,OAAO,EAAE,KAAK,IAAI,CAAC;GACrC,GAAI,WAAW,KAAK,SAAS,EAAE,OAAO,IAAI,CAAC;GAC3C,GAAI,eAAe,SAAS,KAAK,OAAO,EAAE,KAAK,IAAI,CAAC;EACtD;EACA,MAAM,aAAa,SAAS;EAC5B,IAAI,eAAe,KAAA,GAAW,MAAM,SAAS;EAC7C,IAAI,OAAO,KAAK,KAAK,CAAC,CAAC,SAAS,GAAG,QAAa,OAAO,KAAK,KAAK,KAAK,CAAC,CAAC,YAAY,CAAC,CAAC;EACtF,QAAQ;CACV;CAEA,MAAM,QACJ;CACF,MAAM,QAAQ;CACd,MAAM,QAAQ;CAEd,OACE,oBAAC,QAAD;EACE,YAAY;EACH;EACT,WAAU;EAEV,UAAA,qBAAC,QAAD;GACE,WAAW,UAAU;IACnB,MAAM,eAAe;IACrB,KAAK;GACP;GACA,WAAU;GALZ,UAAA;IAOE,oBAAC,MAAD;KAAI,IAAI;KAAS,WAAU;KACxB,UAAA,EAAE,0BAA0B;IAC3B,CAAA;IAEJ,qBAAC,SAAD,EAAA,UAAA,CACE,oBAAC,QAAD;KAAM,WAAW;KAAQ,UAAA,EAAE,yBAAyB;IAAQ,CAAA,GAC5D,oBAAC,SAAD;KACE,MAAK;KACL,OAAO;KACP,WAAW;KACX,WAAW,UAAU,SAAS,MAAM,OAAO,KAAK;KAChD,WAAW;IACZ,CAAA,CACI,EAAA,CAAA;IAEP,qBAAC,YAAD,EAAA,UAAA,CACE,oBAAC,UAAD;KAAQ,WAAW;KAAQ,UAAA,EAAE,0BAA0B;IAAU,CAAA,GACjE,qBAAC,OAAD;KAAK,WAAU;KAAf,UAAA;MACE,oBAAC,UAAD;OACE,MAAK;OACL,gBAAc,UAAU;OACxB,eAAe,SAAS,IAAI;OAC5B,WAAW,4DACT,UAAU,OAAO,uBAAuB;OAGzC,UAAA,EAAE,4BAA4B;MACzB,CAAA;MACP,SAAS,KAAK,WACb,oBAAC,UAAD;OAEE,MAAK;OACL,cAAY;OACZ,gBAAc,UAAU;OACxB,eAAe,SAAS,MAAM;OAC9B,WAAW,6CACT,UAAU,SAAS,qCAAqC;OAE1D,OAAO,EAAE,YAAY,OAAO;MAC7B,GATM,MASN,CACF;MACD,oBAAC,SAAD;OACE,MAAK;OACL,cAAY,EAAE,gCAAgC;OAC9C,OAAO,SAAS;OAChB,WAAW,UAAU,SAAS,MAAM,OAAO,KAAK;OAChD,WAAU;MACX,CAAA;KACE;IACG,CAAA,CAAA,EAAA,CAAA;IAEV,qBAAC,OAAD;KAAK,WAAU;KAAf,UAAA,CACE,qBAAC,SAAD;MAAO,WAAW;MAAlB,UAAA,CACE,oBAAC,SAAD;OACE,MAAK;OACL,SAAS;OACT,WAAW,UAAU,QAAQ,MAAM,OAAO,OAAO;MAClD,CAAA,GACD,oBAAC,QAAD;OAAM,WAAU;OAAiB,UAAA,EAAE,yBAAyB;MAAQ,CAAA,CAC/D;KACP,CAAA,GAAA,qBAAC,SAAD;MAAO,WAAW;MAAlB,UAAA,CACE,oBAAC,SAAD;OACE,MAAK;OACL,SAAS;OACT,WAAW,UAAU,UAAU,MAAM,OAAO,OAAO;MACpD,CAAA,GACD,oBAAC,QAAD;OAAM,WAAU;OAAU,UAAA,EAAE,2BAA2B;MAAQ,CAAA,CAC1D;KACJ,CAAA,CAAA;;IAEL,qBAAC,SAAD;KAAO,WAAW,GAAG,MAAM,GAAG,cAAc,KAAK;KAAjD,UAAA,CACE,oBAAC,SAAD;MACE,MAAK;MACL,UAAU,CAAC;MACX,SAAS,eAAe;MACxB,WAAW,UAAU,QAAQ,MAAM,OAAO,OAAO;KAClD,CAAA,GACA,EAAE,yBAAyB,CACvB;;IAEP,qBAAC,YAAD;KAAU,WAAU;KAApB,UAAA;MACE,oBAAC,UAAD;OAAQ,WAAW;OAAQ,UAAA,EAAE,2BAA2B;MAAU,CAAA;MAClE,qBAAC,UAAD;OACE,OAAO;OACP,WAAW,UAAU,UAAU,MAAM,OAAO,KAAqB;OACjE,WAAW;OAHb,UAAA;QAKE,oBAAC,UAAD;SAAQ,OAAM;SAAQ,UAAA,EAAE,+BAA+B;QAAU,CAAA;QACjE,oBAAC,UAAD;SAAQ,OAAM;SAAQ,UAAA,EAAE,+BAA+B;QAAU,CAAA;QACjE,oBAAC,UAAD;SAAQ,OAAM;SAAQ,UAAA,EAAE,iBAAiB;QAAU,CAAA;QACnD,oBAAC,UAAD;SAAQ,OAAM;SAAO,UAAA,EAAE,gBAAgB;QAAU,CAAA;QACjD,oBAAC,UAAD;SAAQ,OAAM;SAAS,UAAA,EAAE,gCAAgC;QAAU,CAAA;QAClE,WAAW,UACV,oBAAC,UAAD;SAAQ,OAAM;SAAQ,UAAA,EAAE,+BAA+B;QAAU,CAAA;OAE7D;;MACP,WAAW,UACV,qBAAC,OAAD;OAAK,WAAU;OAAf,UAAA,CACE,oBAAC,SAAD;QACE,MAAK;QACL,KAAK;QACL,OAAO;QACP,cAAY,EAAE,4BAA4B;QAC1C,WAAW,UAAU,QAAQ,MAAM,OAAO,KAAK;QAC/C,WAAW,GAAG,MAAM;OACrB,CAAA,GACD,qBAAC,UAAD;QACE,OAAO;QACP,cAAY,EAAE,wBAAwB;QACtC,WAAW,UAAU,OAAO,MAAM,OAAO,KAAY;QACrD,WAAW;QAJb,UAAA;SAMG,eAAe,UACd,oBAAC,UAAD;UAAQ,OAAM;UAAQ,UAAA,EAAE,4BAA4B;SAAU,CAAA;SAEhE,oBAAC,UAAD;UAAQ,OAAM;UAAO,UAAA,EAAE,uBAAuB;SAAU,CAAA;SACxD,oBAAC,UAAD;UAAQ,OAAM;UAAQ,UAAA,EAAE,wBAAwB;SAAU,CAAA;QACpD;OACL,CAAA,CAAA;;MAEN,WAAW,SACV,oBAAC,SAAD;OACE,MAAK;OACL,OAAO;OACP,aAAa,EAAE,2BAA2B;OAC1C,WAAW,UAAU,OAAO,MAAM,OAAO,KAAK;OAC9C,WAAW;MACZ,CAAA;MAEF,WAAW,WACV,oBAAC,UAAD;OACE,OAAO;OACP,cAAY,EAAE,gCAAgC;OAC9C,WAAW,UAAU,QAAQ,MAAM,OAAO,KAAiB;OAC3D,WAAW;OAEV,UAAA,WAAW,KAAK,SACf,oBAAC,UAAD;QAAmB,OAAO;QACvB,UAAA,EAAE,eAAe,KAAK;OACjB,GAFK,IAEL,CACT;MACK,CAAA;MAET,WAAW,UACV,oBAAC,KAAD;OAAG,WAAU;OAAyB,UAAA,EAAE,6BAA6B;MAAK,CAAA;KAEpE;;IAEV,qBAAC,OAAD;KAAK,WAAU;KAAf,UAAA,CACE,oBAAC,UAAD;MACE,MAAK;MACL,SAAS;MACT,WAAU;MAET,UAAA,EAAE,2BAA2B;KACxB,CAAA,GACR,oBAAC,UAAD;MACE,MAAK;MACL,WAAU;MAET,UAAA,EAAE,yBAAyB;KACtB,CAAA,CACL;;GACD;;CACA,CAAA;AAEZ"}