@embedpdf/engine-core 3.0.0-next.13 → 3.0.0-next.15

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 (135) hide show
  1. package/dist/AnnotationList-CkijRHet.d.cts +27163 -0
  2. package/dist/AnnotationList-CkijRHet.d.ts +27163 -0
  3. package/dist/Change-CKoxfTNY.js +889 -0
  4. package/dist/Change-CKoxfTNY.js.map +1 -0
  5. package/dist/Change-CjImsrN0.cjs +1020 -0
  6. package/dist/Change-CjImsrN0.cjs.map +1 -0
  7. package/dist/DocumentRenderService-BfFdFSwI.cjs +120 -0
  8. package/dist/DocumentRenderService-BfFdFSwI.cjs.map +1 -0
  9. package/dist/DocumentRenderService-DV3J9lMz.js +85 -0
  10. package/dist/DocumentRenderService-DV3J9lMz.js.map +1 -0
  11. package/dist/{DocumentSecurityService-_JRjqvoI.d.ts → DocumentSecurityService-CU1M6Q7m.d.ts} +100 -112
  12. package/dist/{DocumentSecurityService-ClTZc0zO.d.cts → DocumentSecurityService-e6vp2de8.d.cts} +100 -112
  13. package/dist/LocalDocumentHandle-D02FMm-Z.cjs +53 -0
  14. package/dist/LocalDocumentHandle-D02FMm-Z.cjs.map +1 -0
  15. package/dist/LocalDocumentHandle-DAPdaOt_.js +30 -0
  16. package/dist/LocalDocumentHandle-DAPdaOt_.js.map +1 -0
  17. package/dist/LocalEngine-DFoBm4B3.d.cts +1565 -0
  18. package/dist/LocalEngine-DPriFujS.d.ts +1565 -0
  19. package/dist/PageInsertBlankInput-CXHAM7l6.cjs +17 -0
  20. package/dist/PageInsertBlankInput-CXHAM7l6.cjs.map +1 -0
  21. package/dist/PageInsertBlankInput-DhVYVJ_S.js +12 -0
  22. package/dist/PageInsertBlankInput-DhVYVJ_S.js.map +1 -0
  23. package/dist/authority-B3BklsB4.js +2239 -0
  24. package/dist/authority-B3BklsB4.js.map +1 -0
  25. package/dist/authority-DLMNR7ff.cjs +2676 -0
  26. package/dist/authority-DLMNR7ff.cjs.map +1 -0
  27. package/dist/builders-CNj0POeY.js +161 -0
  28. package/dist/builders-CNj0POeY.js.map +1 -0
  29. package/dist/builders-Cgdp_YCn.cjs +184 -0
  30. package/dist/builders-Cgdp_YCn.cjs.map +1 -0
  31. package/dist/calibrate-7T3fnP8-.js +2404 -0
  32. package/dist/calibrate-7T3fnP8-.js.map +1 -0
  33. package/dist/calibrate-DJBXnhLE.cjs +2919 -0
  34. package/dist/calibrate-DJBXnhLE.cjs.map +1 -0
  35. package/dist/charmap-Cprti1ta.js +239 -0
  36. package/dist/charmap-Cprti1ta.js.map +1 -0
  37. package/dist/charmap-aYlefQP9.cjs +304 -0
  38. package/dist/charmap-aYlefQP9.cjs.map +1 -0
  39. package/dist/conformance.cjs +16753 -5247
  40. package/dist/conformance.cjs.map +1 -1
  41. package/dist/conformance.d.cts +928 -165
  42. package/dist/conformance.d.ts +928 -165
  43. package/dist/conformance.js +16731 -5268
  44. package/dist/conformance.js.map +1 -1
  45. package/dist/format-Bp3QFSH1.cjs +574 -0
  46. package/dist/format-Bp3QFSH1.cjs.map +1 -0
  47. package/dist/format-Dgg428Kb.js +461 -0
  48. package/dist/format-Dgg428Kb.js.map +1 -0
  49. package/dist/index.cjs +330 -103
  50. package/dist/index.d.cts +2 -2
  51. package/dist/index.d.ts +2 -2
  52. package/dist/index.js +14 -5
  53. package/dist/pageRefs-B3ur7Ckm.cjs +51 -0
  54. package/dist/pageRefs-B3ur7Ckm.cjs.map +1 -0
  55. package/dist/pageRefs-DkbuxSCV.js +40 -0
  56. package/dist/pageRefs-DkbuxSCV.js.map +1 -0
  57. package/dist/public.cjs +57 -0
  58. package/dist/public.d.cts +5 -0
  59. package/dist/public.d.ts +5 -0
  60. package/dist/public.js +9 -0
  61. package/dist/resolveAnnotationDraft-7Ke4nV7F.cjs +3646 -0
  62. package/dist/resolveAnnotationDraft-7Ke4nV7F.cjs.map +1 -0
  63. package/dist/resolveAnnotationDraft-CUpf0SMh.js +3167 -0
  64. package/dist/resolveAnnotationDraft-CUpf0SMh.js.map +1 -0
  65. package/dist/{resolver-inAVzsWt.js → resolver-CzxmD9Ck.js} +294 -144
  66. package/dist/resolver-CzxmD9Ck.js.map +1 -0
  67. package/dist/{resolver-CYVNV4hn.cjs → resolver-D2OCtE8F.cjs} +347 -143
  68. package/dist/resolver-D2OCtE8F.cjs.map +1 -0
  69. package/dist/runtime-Cl0v56mm.d.ts +2032 -0
  70. package/dist/runtime-p1WDzDo4.d.cts +2032 -0
  71. package/dist/runtime.cjs +733 -284
  72. package/dist/runtime.cjs.map +1 -1
  73. package/dist/runtime.d.cts +5 -1348
  74. package/dist/runtime.d.ts +5 -1348
  75. package/dist/runtime.js +396 -179
  76. package/dist/runtime.js.map +1 -1
  77. package/dist/schema-C-gU4vj7.cjs +3034 -0
  78. package/dist/schema-C-gU4vj7.cjs.map +1 -0
  79. package/dist/schema-DzlUNk38.js +2081 -0
  80. package/dist/schema-DzlUNk38.js.map +1 -0
  81. package/dist/schemas-Berf1swF.cjs +2481 -0
  82. package/dist/schemas-Berf1swF.cjs.map +1 -0
  83. package/dist/schemas-D6xOGjqg.js +1654 -0
  84. package/dist/schemas-D6xOGjqg.js.map +1 -0
  85. package/dist/subtype-CG4WpIRj.js +129 -0
  86. package/dist/subtype-CG4WpIRj.js.map +1 -0
  87. package/dist/subtype-aDt5TFmK.cjs +158 -0
  88. package/dist/subtype-aDt5TFmK.cjs.map +1 -0
  89. package/dist/validation.cjs +578 -0
  90. package/dist/validation.cjs.map +1 -0
  91. package/dist/validation.d.cts +174 -0
  92. package/dist/validation.d.ts +174 -0
  93. package/dist/validation.js +571 -0
  94. package/dist/validation.js.map +1 -0
  95. package/dist/value-BFS1R8ek.cjs +435 -0
  96. package/dist/value-BFS1R8ek.cjs.map +1 -0
  97. package/dist/value-Dhc8eYcx.js +340 -0
  98. package/dist/value-Dhc8eYcx.js.map +1 -0
  99. package/dist/viewport-BJW13EGZ.js +540 -0
  100. package/dist/viewport-BJW13EGZ.js.map +1 -0
  101. package/dist/viewport-DlL5Bxbg.cjs +671 -0
  102. package/dist/viewport-DlL5Bxbg.cjs.map +1 -0
  103. package/dist/wire.cjs +1056 -379
  104. package/dist/wire.cjs.map +1 -1
  105. package/dist/wire.d.cts +15069 -725
  106. package/dist/wire.d.ts +15069 -725
  107. package/dist/wire.js +825 -239
  108. package/dist/wire.js.map +1 -1
  109. package/package.json +10 -1
  110. package/dist/AbortError-Cq2igpZ6.cjs +0 -38
  111. package/dist/AbortError-Cq2igpZ6.cjs.map +0 -1
  112. package/dist/AbortError-DHqPBnYc.js +0 -27
  113. package/dist/AbortError-DHqPBnYc.js.map +0 -1
  114. package/dist/AnnotationListSnapshot-D3mFut1e.d.cts +0 -6871
  115. package/dist/AnnotationListSnapshot-D3mFut1e.d.ts +0 -6871
  116. package/dist/Engine-Bx0NOfmd.d.cts +0 -1264
  117. package/dist/Engine-DxtpCYcP.d.ts +0 -1264
  118. package/dist/PageInsertBlankInput-CqXBmFhN.cjs +0 -449
  119. package/dist/PageInsertBlankInput-CqXBmFhN.cjs.map +0 -1
  120. package/dist/PageInsertBlankInput-cHq9-i-z.js +0 -378
  121. package/dist/PageInsertBlankInput-cHq9-i-z.js.map +0 -1
  122. package/dist/builders-Bqm8yTpi.cjs +0 -3564
  123. package/dist/builders-Bqm8yTpi.cjs.map +0 -1
  124. package/dist/builders-Dqo2X-dt.js +0 -3121
  125. package/dist/builders-Dqo2X-dt.js.map +0 -1
  126. package/dist/fold-2V29cxCV.cjs +0 -447
  127. package/dist/fold-2V29cxCV.cjs.map +0 -1
  128. package/dist/fold-CdEJTBTn.js +0 -334
  129. package/dist/fold-CdEJTBTn.js.map +0 -1
  130. package/dist/resolver-CYVNV4hn.cjs.map +0 -1
  131. package/dist/resolver-inAVzsWt.js.map +0 -1
  132. package/dist/schemas-BLARNCgx.js +0 -3113
  133. package/dist/schemas-BLARNCgx.js.map +0 -1
  134. package/dist/schemas-DIqFMmrC.cjs +0 -4468
  135. package/dist/schemas-DIqFMmrC.cjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Change-CjImsrN0.cjs","names":["EngineError","EngineErrorCode","EngineError","EngineErrorCode","applyAnnotationPatch","formWidget","annotationOfDraft","EngineError","EngineErrorCode","resolveAnnotationResources","annotationResourceBuffers","withFileFromResource","hasAnnotationResources"],"sources":["../src/mutation/AttachmentMutationResults.ts","../src/forms/write.ts","../src/forms/widgets.ts","../src/forms/predict.ts","../src/forms/effects.ts","../src/mutation/Change.ts"],"sourcesContent":["import type { MutationMeta } from './MutationMeta';\nimport type { Attachment, AttachmentRef } from '../dto/Attachment';\n\n/**\n * The `meta` of an attachment write: the attachments it created or deleted.\n * On the cloud, `cacheDelta` advances `docVersion` and `attachmentsVersion`\n * (which re-keys the `/attachments@…` and `/attachment-files/…@…` leaves)\n * and no per-page pin.\n */\nexport interface AttachmentMutationMeta extends MutationMeta {\n changed: AttachmentRef[];\n}\n\n/**\n * Result of creating a document-level embedded file: the new attachment,\n * read back after the write. Its `index` reflects the name-sorted position\n * (creating shifts other indices; refs never move).\n */\nexport interface AttachmentCreateResult {\n attachment: Attachment;\n meta: AttachmentMutationMeta;\n}\n\n/** A delete: nothing exists after it, so only `meta`. */\nexport interface AttachmentDeleteResult {\n meta: AttachmentMutationMeta;\n}\n\n/**\n * What a delete removed, as its `attachments.deleted` event names it for\n * listeners that didn't make the call.\n */\nexport function deletedAttachmentOf(result: AttachmentDeleteResult): AttachmentRef | null {\n return result.meta.changed[0] ?? null;\n}\n","/**\n * What a value write is, worked out from the field it writes: the one place\n * the engine checks a value against its field, shared by the engine (before\n * it writes) and a viewer (before it shows the write, `predict.ts`).\n */\nimport type { FormFieldDTO, FormFieldFamily } from './field';\nimport type { FormFieldValue } from './value';\nimport type { FormValueEntry } from './value-entry';\nimport { EngineError } from '../errors/EngineError';\nimport { EngineErrorCode } from '../errors/EngineErrorCode';\nimport type { Coordinates } from '../pageSpace/coordinates';\n\n/**\n * A value write, as the field's family takes it: a text field's text, a\n * toggle's on-state (`null` clears the group), or a choice field's option\n * values (free text for a dropdown that allows editing).\n */\nexport type FieldValueWrite =\n | { kind: 'text'; value: string }\n | { kind: 'toggle'; state: string | null }\n | { kind: 'choice'; values: string[] };\n\n/** The shapes each family takes, for the message when a value doesn't fit. */\nconst TAKES: Partial<Record<FormFieldFamily, string>> = {\n text: '{ value }',\n checkbox: '{ checked } or { value }',\n radio: '{ value }',\n combobox: '{ value }',\n listbox: '{ selectedValues }',\n};\n\n/**\n * The write `value` makes for `field`, checked before anything is written:\n * the shape must be one the family takes, a toggle's value must be the\n * export value of one of its widgets (a radio group that must keep a choice\n * can't be cleared), and a choice must be option values (free text for a\n * dropdown that allows editing). `InvalidArg` otherwise.\n */\nexport function fieldValueWriteOf(\n field: FormFieldDTO<Coordinates>,\n value: FormFieldValue,\n): FieldValueWrite {\n switch (field.family) {\n case 'text':\n if ('value' in value) return { kind: 'text', value: value.value ?? '' };\n break;\n case 'checkbox':\n if ('checked' in value) {\n if (!value.checked) return { kind: 'toggle', state: null };\n const first = field.widgets[0];\n if (!first) throw invalidValue(`'${field.name}' has no widget to check`);\n return { kind: 'toggle', state: first.onState };\n }\n if ('value' in value) return { kind: 'toggle', state: toggleStateOf(field, value.value) };\n break;\n case 'radio':\n if ('value' in value) {\n const state = toggleStateOf(field, value.value);\n if (state === null && field.noToggleToOff) {\n throw invalidValue(`'${field.name}' must keep a choice: it can't be cleared`);\n }\n return { kind: 'toggle', state };\n }\n break;\n case 'combobox':\n if ('value' in value) return choiceOf(field, value.value === null ? [] : [value.value]);\n break;\n case 'listbox':\n if ('selectedValues' in value) return choiceOf(field, value.selectedValues);\n break;\n default:\n throw invalidValue(`${field.family} fields hold no value you can set`);\n }\n throw invalidValue(`a ${field.family} field takes ${TAKES[field.family]}, not ${shapeOf(value)}`);\n}\n\n/** What a choice field's default is checked against: its options and how it takes values. */\nexport interface ChoiceDefaultTarget {\n family: 'combobox' | 'listbox';\n options: readonly { value: string }[];\n /** A dropdown that allows free text. */\n edit?: boolean;\n /** A list box that takes several values. */\n multiSelect?: boolean;\n}\n\n/**\n * Check a choice field's default (`/DV`) before it is written: option values\n * (one free text for a dropdown that allows editing), none twice, and one\n * value unless the list box takes several. `InvalidArg` otherwise.\n */\nexport function assertChoiceDefault(target: ChoiceDefaultTarget, values: readonly string[]): void {\n const invalid = (message: string) =>\n new EngineError(EngineErrorCode.InvalidArg, message, { details: { field: 'defaultValue' } });\n if (new Set(values).size !== values.length) throw invalid('the default values must not repeat');\n if (values.length > 1 && !(target.family === 'listbox' && target.multiSelect)) {\n throw invalid(\n `a ${target.family === 'listbox' ? 'list without multiSelect' : 'dropdown'} has one default`,\n );\n }\n const freeText = target.family === 'combobox' && target.edit === true;\n const optionValues = new Set(target.options.map((option) => option.value));\n const unknown = values.find((value) => !optionValues.has(value));\n if (unknown !== undefined && !freeText) {\n throw invalid(\n `'${unknown}' is not an option value of the ${target.family === 'listbox' ? 'list' : 'dropdown'}`,\n );\n }\n}\n\n/** Whether `write` would leave `field` as it is. */\nexport function isNoOpWrite(field: FormFieldDTO<Coordinates>, write: FieldValueWrite): boolean {\n switch (write.kind) {\n case 'text':\n return field.family === 'text' && field.value === write.value;\n case 'toggle':\n return (\n (field.family === 'checkbox' || field.family === 'radio') &&\n field.widgets.every((widget) => widget.checked === (widget.onState === write.state))\n );\n case 'choice':\n if (field.family === 'combobox') {\n return write.values.length === 0 ? field.value === '' : field.value === write.values[0];\n }\n return (\n field.family === 'listbox' &&\n field.selectedValues.length === write.values.length &&\n field.selectedValues.every((value, index) => value === write.values[index])\n );\n }\n}\n\n/**\n * Whether a reset would leave `field` as it is: its value is its default, and\n * a checkbox's or radio group's buttons show that default.\n */\nexport function isAtDefault(field: FormFieldDTO<Coordinates>): boolean {\n if (field.valueEntry.kind === 'unsupported') return false;\n if (!valueEntriesEqual(field.valueEntry, field.defaultValueEntry)) return false;\n if (field.family !== 'checkbox' && field.family !== 'radio') return true;\n const entry = field.defaultValueEntry;\n const state = entry.kind === 'scalar' ? entry.value : null;\n return field.widgets.every((widget) => widget.checked === (widget.onState === state));\n}\n\n/** Whether two value entries hold the same value. */\nexport function valueEntriesEqual(left: FormValueEntry, right: FormValueEntry): boolean {\n if (left.kind !== right.kind) return false;\n if (left.kind === 'scalar' && right.kind === 'scalar') return left.value === right.value;\n if (left.kind === 'array' && right.kind === 'array') {\n return (\n left.values.length === right.values.length &&\n left.values.every((value, index) => value === right.values[index])\n );\n }\n return true;\n}\n\n/** A checkbox's or radio group's on-state for an export value; `'Off'` and `null` clear it. */\nfunction toggleStateOf(\n field: Extract<FormFieldDTO<Coordinates>, { family: 'checkbox' | 'radio' }>,\n exportValue: string | null,\n): string | null {\n if (exportValue === null || exportValue === 'Off') return null;\n const widget = field.widgets.find((candidate) => candidate.exportValue === exportValue);\n if (!widget) {\n throw invalidValue(`no widget of '${field.name}' has the export value '${exportValue}'`);\n }\n return widget.onState;\n}\n\nfunction choiceOf(\n field: Extract<FormFieldDTO<Coordinates>, { family: 'combobox' | 'listbox' }>,\n values: string[],\n): FieldValueWrite {\n if (new Set(values).size !== values.length) {\n throw invalidValue('the values must not repeat');\n }\n if (field.family === 'listbox' && !field.multiSelect && values.length > 1) {\n throw invalidValue(`'${field.name}' takes one value (it has no multiSelect)`);\n }\n const optionValues = new Set(field.options.map((option) => option.value));\n const freeText = field.family === 'combobox' && field.edit && values.length === 1;\n const unknown = values.find((value) => !optionValues.has(value));\n if (!freeText && unknown !== undefined) {\n throw invalidValue(`'${unknown}' is not an option value of '${field.name}'`);\n }\n return { kind: 'choice', values };\n}\n\nfunction shapeOf(value: FormFieldValue): string {\n if ('checked' in value) return '{ checked }';\n if ('selectedValues' in value) return '{ selectedValues }';\n return '{ value }';\n}\n\nfunction invalidValue(message: string): EngineError {\n return new EngineError(EngineErrorCode.InvalidArg, message, { details: { field: 'value' } });\n}\n","/**\n * What a form widget takes, by its field's family: the rules the engine\n * checks a widget placement or patch with, and the row a patch leaves.\n */\nimport type { FormFieldFamily } from './field';\nimport type { WidgetAnnotation, WidgetPatch } from '../annotation/kinds/widget';\nimport type { WidgetCheckStyle } from '../annotation/primitives';\nimport { EngineError } from '../errors/EngineError';\nimport { EngineErrorCode } from '../errors/EngineErrorCode';\nimport type { PageBox } from '../geometry/pageSpace';\nimport type { Coordinates } from '../pageSpace/coordinates';\nimport { applyAnnotationPatch } from '../pageSpace/helpers';\n\n/**\n * A widget placement or patch as a `family` widget takes it. `/MK /CA` is a\n * push button's caption and a checkbox's or radio button's symbol\n * (`checkStyle`), so each goes on its own family's widgets only: on another\n * widget, a `null` (as its row reads) is dropped, and a value is refused.\n */\nexport function fitWidgetToFamily<\n T extends { readonly caption?: string | null; readonly checkStyle?: WidgetCheckStyle | null },\n>(family: FormFieldFamily, value: T): T {\n const toggle = family === 'checkbox' || family === 'radio';\n const fitted = fitToFamily(family, value, 'caption', family === 'pushbutton', \"a push button's\");\n return fitToFamily(family, fitted, 'checkStyle', toggle, \"a checkbox's or radio button's\");\n}\n\nfunction fitToFamily<T extends Record<string, unknown>>(\n family: FormFieldFamily,\n value: T,\n key: 'caption' | 'checkStyle',\n takes: boolean,\n whose: string,\n): T {\n if (takes || value[key] === undefined) return value;\n if (value[key] !== null) {\n const widget = family === 'unknown' ? 'this widget' : `a ${family} field's widget`;\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n `'${key}' applies to ${whose} widgets, not to ${widget}`,\n { details: { field: key } },\n );\n }\n const { [key]: _none, ...rest } = value;\n return rest as T;\n}\n\n/**\n * `forms.updateWidget`: the row a widget patch leaves, as an annotation\n * patch leaves it (a move keeps the look), checked against the widget's\n * family first. A new box or turn moves where it stands (`standingRectOf`).\n */\nexport function widgetAfterPatch<C extends Coordinates>(\n row: WidgetAnnotation<C>,\n patch: WidgetPatch,\n): WidgetAnnotation<C> {\n const fitted = fitWidgetToFamily(row.fieldFamily, patch);\n const after = applyAnnotationPatch(\n row as never,\n { subtype: 'widget', ...fitted } as never,\n ) as unknown as WidgetAnnotation<C>;\n const placed = ['box', 'rect', 'rotation'].some((key) => key in fitted);\n if (!placed) return after;\n // Rows are in page space here (a box is `{ x, y, width, height }`).\n return { ...after, rect: standingRectOf(after.box as PageBox, after.rotation) as never };\n}\n\n/**\n * Where a widget stands on the page: its box, with its sides swapped under a\n * quarter turn (its contents turn, the frame keeps its place).\n */\nexport function standingRectOf<B extends { x: number; y: number; width: number; height: number }>(\n box: B,\n rotation: number | null | undefined,\n): B {\n const turn = (((rotation ?? 0) % 360) + 360) % 360;\n if (turn !== 90 && turn !== 270) return box;\n const { x, y, width, height } = box;\n return {\n ...box,\n x: x + (width - height) / 2,\n y: y + (height - width) / 2,\n width: height,\n height: width,\n };\n}\n","/**\n * What a form op leaves, worked out before the engine runs it: the field and\n * the rows of its widgets, as a read of them would return them afterwards.\n * The engine's rules, as plain functions, so a viewer can show a write at\n * once and the engine follows the same rules (`runFormPredictionConformance`\n * checks every op on both engines).\n *\n * What these can't know is left as it was, and a read after the write tells:\n * dates and who filled a field in, the fonts a document's own default\n * appearance names, and a `/V` an ancestor field holds (a cleared value then\n * reads as an empty string, not as none).\n */\nimport type { FormFieldOptionInput, FormFieldDraft, WidgetPlacement } from './draft';\nimport type { FormFieldDisplay } from './effects';\nimport type { FormFieldDTO, FormFieldOption, FormFieldWidget, ToggleFieldWidget } from './field';\nimport type { FormFieldPatch } from './patch';\nimport type { FormFieldValue } from './value';\nimport type { FormValueEntry } from './value-entry';\nimport { standingRectOf } from './widgets';\nimport { assertChoiceDefault, fieldValueWriteOf } from './write';\nimport type { Annotation } from '../annotation/kinds';\nimport type { WidgetAnnotation } from '../annotation/kinds/widget';\nimport { EngineError } from '../errors/EngineError';\nimport { EngineErrorCode } from '../errors/EngineErrorCode';\nimport type { AnnotationRef } from '../identity/AnnotationRef';\nimport { formWidget } from '../identity/FormFieldRef';\nimport type { Coordinates, PageCoordinates } from '../pageSpace/coordinates';\nimport { annotationOfDraft } from '../pageSpace/helpers';\n\n/** A field and the rows of its widgets: what a form op changes, as its answer reports them. */\nexport interface FieldWithWidgets<C extends Coordinates = PageCoordinates> {\n readonly field: FormFieldDTO<C>;\n /** The rows of the field's widgets, as the form's `widgets` holds them. */\n readonly widgets: readonly WidgetAnnotation<C>[];\n}\n\n/* ── values ─────────────────────────────────────────────────────────────── */\n\n/**\n * `forms.setValue`: a text field holds the text, cut to its maximum length\n * (in characters); a checkbox checks every widget with the target's export\n * value and on-state; a radio group checks the first button with the value,\n * or every one with it when its radios move in unison; a choice field holds\n * its option values in option order, or a dropdown's free text. Refuses what\n * the engine refuses (`fieldValueWriteOf`).\n */\nexport function fieldAfterValue<C extends Coordinates>(\n current: FieldWithWidgets<C>,\n value: FormFieldValue,\n): FieldWithWidgets<C> {\n const { field } = current;\n const write = fieldValueWriteOf(field, value);\n switch (write.kind) {\n case 'text': {\n if (field.family !== 'text') return current;\n const text = firstCharacters(write.value, field.maxLength);\n if (text === field.value) return current;\n return redrawn(\n { ...field, value: text, valueEntry: { kind: 'scalar', value: text } },\n current,\n );\n }\n case 'toggle': {\n if (field.family !== 'checkbox' && field.family !== 'radio') return current;\n const target = field.widgets.findIndex((widget) => widget.onState === write.state);\n return toggled(current, write.state === null ? -1 : target);\n }\n case 'choice': {\n if (field.family !== 'combobox' && field.family !== 'listbox') return current;\n return redrawn(choiceFieldWith(field, write.values), current);\n }\n }\n}\n\n/**\n * `forms.reset`: back to the default value. A text field holds its default\n * (or nothing); a choice field its default options; a checkbox or radio\n * group checks the widget its default names, or none.\n */\nexport function fieldAfterReset<C extends Coordinates>(\n current: FieldWithWidgets<C>,\n): FieldWithWidgets<C> {\n const { field } = current;\n const defaults = field.defaultValueEntry;\n switch (field.family) {\n case 'text': {\n if (defaults.kind === 'array' || defaults.kind === 'unsupported') {\n throw notReset(field);\n }\n const value = defaults.kind === 'scalar' ? defaults.value : '';\n const entry: FormValueEntry = defaults.kind === 'scalar' ? defaults : { kind: 'none' };\n return redrawn({ ...field, value, valueEntry: entry }, current);\n }\n case 'checkbox':\n case 'radio': {\n if (defaults.kind === 'array' || defaults.kind === 'unsupported') throw notReset(field);\n const state = defaults.kind === 'scalar' ? defaults.value : null;\n if (state === null || state === 'Off') return toggled(current, -1);\n const target = widgetNamedBy(field.widgets, state);\n if (target < 0) throw notReset(field);\n return toggled(current, target);\n }\n case 'combobox':\n case 'listbox': {\n if (defaults.kind === 'unsupported') throw notReset(field);\n let values =\n defaults.kind === 'scalar'\n ? [defaults.value]\n : defaults.kind === 'array'\n ? [...defaults.values]\n : [];\n // An empty default selects nothing, unless an option's value is empty.\n if (values.length === 1 && values[0] === '' && !choiceMatches(field, values)) values = [];\n if (!choiceMatches(field, values) && !freeTextAllowed(field, values)) throw notReset(field);\n return redrawn(choiceFieldWith(field, values), current);\n }\n default:\n throw notReset(field);\n }\n}\n\n/**\n * `forms.setDisplay`, on each widget's flags, as Acrobat's `Field.display`\n * sets them: visible and printed; hidden; visible but not printed; printed\n * but not shown on screen.\n */\nexport function widgetsAfterDisplay<C extends Coordinates>(\n widgets: readonly WidgetAnnotation<C>[],\n display: FormFieldDisplay,\n): WidgetAnnotation<C>[] {\n const flags = DISPLAY_FLAGS[display];\n return widgets.map((row) =>\n Object.keys(flags).every((key) => row[key as keyof typeof flags] === flags[key as never])\n ? row\n : { ...row, ...flags },\n );\n}\n\nconst DISPLAY_FLAGS = {\n visible: { invisible: false, hidden: false, noView: false, print: true },\n hidden: { invisible: false, hidden: true, noView: false, print: true },\n noPrint: { invisible: false, hidden: false, noView: false, print: false },\n noView: { hidden: false, noView: true, print: true },\n} as const satisfies Record<FormFieldDisplay, Partial<Record<string, boolean>>>;\n\n/* ── creating and changing fields ───────────────────────────────────────── */\n\n/**\n * The default (`/DV`) a draft gives its field: a text field's or dropdown's\n * one value, a list box's option values in option order; none without one.\n */\nexport function defaultEntryOfDraft<C extends Coordinates>(\n draft: FormFieldDraft<C>,\n): FormValueEntry {\n if (\n (draft.family === 'combobox' || draft.family === 'listbox') &&\n draft.defaultValue !== undefined\n ) {\n const values = Array.isArray(draft.defaultValue) ? draft.defaultValue : [draft.defaultValue];\n assertChoiceDefault({ ...draft, options: draft.options ?? [] }, values);\n }\n switch (draft.family) {\n case 'text':\n case 'combobox':\n return draft.defaultValue !== undefined ? scalar(draft.defaultValue) : none();\n case 'listbox':\n return choiceEntryOf(\n inOptionOrder((draft.options ?? []).map(optionOf), draft.defaultValue ?? []),\n );\n default:\n return none();\n }\n}\n\n/** What a draft alone doesn't say about the field `forms.create` makes. */\nexport interface FieldDraftContext {\n /** The field's object number. */\n readonly objectNumber: number;\n /** Its widgets' refs, in `draft.widgets` order. */\n readonly widgets: readonly AnnotationRef[];\n /** The group a draft without one goes in: the session's own (`identity.groupId`). */\n readonly groupId?: string | null;\n /** Who creates it, and when, as the engine stamps it. Left out, a read says `null`. */\n readonly createdBy?: string | null;\n readonly createdAt?: string | null;\n /** The name each widget gets (a fresh UUIDv7 the engine mints), in `widgets` order. */\n readonly widgetNames?: readonly string[];\n}\n\n/**\n * `forms.create`: the field and its widgets as a read of them returns them.\n * Every flag the draft doesn't set is off, the value is empty (a default\n * only sets the default), a checkbox's export value is `'Yes'` unless its\n * widget names one, and a toggle's widgets start off.\n */\nexport function formFieldOfDraft(\n draft: FormFieldDraft,\n context: FieldDraftContext,\n): FieldWithWidgets {\n const placements = draft.widgets ?? [];\n const rows = placements.map((placement, at) =>\n widgetRowOfPlacement(draft, placement, {\n ref: context.widgets[at]!,\n field: context.objectNumber,\n nm: context.widgetNames?.[at],\n }),\n );\n const widgets: FormFieldWidget[] = rows.map((row) =>\n formWidget(objectNumberOf(row.ref), row.page),\n );\n const options = (\n draft.family === 'combobox' || draft.family === 'listbox' ? (draft.options ?? []) : []\n ).map(optionOf);\n const base = {\n ref: { kind: 'objectNumber' as const, objectNumber: context.objectNumber },\n name: draft.name,\n origin: 'acroform' as const,\n readOnly: draft.readOnly ?? false,\n required: draft.required ?? false,\n noExport: draft.noExport ?? false,\n alternateName: draft.alternateName ?? null,\n mappingName: draft.mappingName ?? null,\n valueEntry: { kind: 'none' } as FormValueEntry,\n defaultValueEntry: { kind: 'none' } as FormValueEntry,\n groupId: draft.groupId ?? context.groupId ?? null,\n createdBy: context.createdBy ?? null,\n createdAt: context.createdAt ?? null,\n filledBy: null,\n filledByName: null,\n filledAt: null,\n importedBy: null,\n };\n let field: FormFieldDTO;\n switch (draft.family) {\n case 'text': {\n const defaultValue = draft.defaultValue ?? '';\n field = {\n ...base,\n family: 'text',\n defaultValueEntry: defaultEntryOfDraft(draft),\n value: '',\n defaultValue,\n maxLength: draft.maxLength ?? null,\n multiline: draft.multiline ?? false,\n password: draft.password ?? false,\n comb: draft.comb ?? false,\n widgets,\n };\n break;\n }\n case 'checkbox': {\n const toggles = placements.map((placement, at) =>\n toggleWidgetOf(widgets[at]!, placement.exportValue ?? 'Yes'),\n );\n field = {\n ...base,\n family: 'checkbox',\n checked: false,\n exportValue: toggles[0]?.exportValue ?? 'Yes',\n widgets: toggles,\n };\n break;\n }\n case 'radio': {\n const toggles = placements.map((placement, at) =>\n toggleWidgetOf(widgets[at]!, placement.exportValue ?? ''),\n );\n field = {\n ...base,\n family: 'radio',\n value: 'Off',\n radiosInUnison: draft.radiosInUnison ?? false,\n noToggleToOff: draft.noToggleToOff ?? false,\n widgets: toggles,\n };\n break;\n }\n case 'combobox':\n field = {\n ...base,\n family: 'combobox',\n defaultValueEntry: defaultEntryOfDraft(draft),\n value: '',\n defaultValue: draft.defaultValue ?? '',\n edit: draft.edit ?? false,\n options,\n widgets,\n };\n break;\n case 'listbox': {\n const defaults = draft.defaultValue ?? [];\n field = {\n ...base,\n family: 'listbox',\n defaultValueEntry: defaultEntryOfDraft(draft),\n selectedValues: [],\n defaultValue: inOptionOrder(options, defaults),\n multiSelect: draft.multiSelect ?? false,\n options,\n topIndex: 0,\n widgets,\n };\n break;\n }\n default:\n field = { ...base, family: draft.family, widgets };\n }\n return { field, widgets: rows };\n}\n\n/**\n * `forms.update`: the settings the patch names. A new name replaces the\n * field's own segment of its dotted name; new options keep what is still\n * selected (an editable dropdown keeps its free text) and its default the\n * same way; `null` clears a limit, a name or a default.\n */\nexport function formFieldAfter<C extends Coordinates>(\n current: FieldWithWidgets<C>,\n patch: FormFieldPatch,\n): FieldWithWidgets<C> {\n const given = patch as Record<string, unknown>;\n let field = { ...current.field } as FormFieldDTO<C> & Record<string, unknown>;\n if (patch.name !== undefined) {\n const parent = field.name.lastIndexOf('.');\n field.name = parent < 0 ? patch.name : `${field.name.slice(0, parent + 1)}${patch.name}`;\n }\n for (const flag of FLAGS) {\n if (typeof given[flag] === 'boolean' && flag in field) field[flag] = given[flag];\n }\n if (patch.alternateName !== undefined) field.alternateName = patch.alternateName || null;\n if (patch.mappingName !== undefined) field.mappingName = patch.mappingName || null;\n if (patch.groupId !== undefined) field.groupId = patch.groupId;\n if (field.family === 'text') {\n if ('maxLength' in patch && patch.maxLength !== undefined) field.maxLength = patch.maxLength;\n if ('defaultValue' in patch && patch.defaultValue !== undefined) {\n const value = patch.defaultValue as string | null;\n field.defaultValue = value ?? '';\n field.defaultValueEntry = value === null ? none() : scalar(value);\n }\n }\n let redraw = false;\n if (field.family === 'combobox' || field.family === 'listbox') {\n if ('options' in patch && patch.options) {\n field = withOptions(field, patch.options.map(optionOf)) as typeof field;\n redraw = true;\n }\n if ('defaultValue' in patch && patch.defaultValue !== undefined) {\n const values =\n patch.defaultValue === null\n ? []\n : Array.isArray(patch.defaultValue)\n ? patch.defaultValue\n : [patch.defaultValue];\n assertChoiceDefault(field, values);\n field = withDefault(field, values) as typeof field;\n }\n }\n const after = { ...current, field: field as FormFieldDTO<C> };\n return redraw ? redrawn(after.field, after) : after;\n}\n\nconst FLAGS = [\n 'readOnly',\n 'required',\n 'noExport',\n 'multiline',\n 'password',\n 'comb',\n 'radiosInUnison',\n 'noToggleToOff',\n 'edit',\n 'multiSelect',\n] as const;\n\n/* ── the rules underneath ───────────────────────────────────────────────── */\n\n/** The first `limit` characters of `text` (characters, as the file counts them); all without a limit. */\nfunction firstCharacters(text: string, limit: number | null): string {\n if (!limit) return text;\n const characters = Array.from(text);\n return characters.length > limit ? characters.slice(0, limit).join('') : text;\n}\n\n/** The field, with every widget's appearance drawn again (a text or choice write). */\nfunction redrawn<C extends Coordinates>(\n field: FormFieldDTO<C>,\n current: FieldWithWidgets<C>,\n): FieldWithWidgets<C> {\n return {\n field,\n widgets: current.widgets.map((row) =>\n row.hasAppearance ? row : { ...row, hasAppearance: true },\n ),\n };\n}\n\n/**\n * The widget a checkbox's or radio group's default names: the one whose\n * on-state it is, or, when none is, the one at that position (a field with\n * `/Opt` written by a tool that names its widgets by position). `-1`: none.\n */\nfunction widgetNamedBy(widgets: readonly ToggleFieldWidget[], state: string): number {\n const named = widgets.findIndex((widget) => widget.onState === state);\n if (named >= 0 || !/^\\d+$/.test(state)) return named;\n return Number(state) < widgets.length ? Number(state) : -1;\n}\n\n/**\n * A checkbox or radio group with widget `target` checked (`-1`: none), and\n * the widgets that go with it: every widget with its export value and\n * on-state for a checkbox or radios in unison, otherwise that one. Its value\n * names the checked widget's on-state (`/V` names the appearance state that\n * is on), or `Off`.\n */\nfunction toggled<C extends Coordinates>(\n current: FieldWithWidgets<C>,\n target: number,\n): FieldWithWidgets<C> {\n const field = current.field;\n if (field.family !== 'checkbox' && field.family !== 'radio') return current;\n const unison = field.family === 'checkbox' || field.radiosInUnison;\n const on = target >= 0 ? field.widgets[target]! : null;\n const toggles = field.widgets.map((widget, at): ToggleFieldWidget => {\n const checked =\n on !== null &&\n (unison\n ? widget.exportValue === on.exportValue && widget.onState === on.onState\n : at === target);\n return widget.checked === checked ? widget : { ...widget, checked };\n });\n const valueEntry: FormValueEntry = scalar(on ? on.onState : 'Off');\n const next =\n field.family === 'checkbox'\n ? {\n ...field,\n widgets: toggles,\n valueEntry,\n checked: toggles.some((widget) => widget.checked),\n }\n : {\n ...field,\n widgets: toggles,\n valueEntry,\n value: toggles.find((widget) => widget.checked)?.exportValue ?? 'Off',\n };\n const states = new Map(\n toggles.map((widget) => [widget.objectNumber, widget.checked ? widget.onState : 'Off']),\n );\n const widgets = current.widgets.map((row) => {\n const state = states.get(objectNumberOf(row.ref));\n return state === undefined || row.appearanceState === state\n ? row\n : { ...row, appearanceState: state };\n });\n return { field: next, widgets };\n}\n\n/** The option indexes `values` name, each the first option with that value, in option order. */\nfunction matchedIndexes(options: readonly FormFieldOption[], values: readonly string[]): number[] {\n const indexes = new Set<number>();\n for (const value of values) {\n const at = options.findIndex((option) => option.value === value);\n if (at >= 0) indexes.add(at);\n }\n return [...indexes].sort((left, right) => left - right);\n}\n\nconst choiceMatches = (\n field: { options: readonly FormFieldOption[] },\n values: readonly string[],\n): boolean => values.every((value) => field.options.some((option) => option.value === value));\n\nconst freeTextAllowed = (field: FormFieldDTO<Coordinates>, values: readonly string[]): boolean =>\n field.family === 'combobox' && field.edit && values.length === 1;\n\n/** A choice field holding `values`: its options' selection, its value and `/V`. */\nfunction choiceFieldWith<C extends Coordinates>(\n field: Extract<FormFieldDTO<C>, { family: 'combobox' | 'listbox' }>,\n values: readonly string[],\n): FormFieldDTO<C> {\n const matched = choiceMatches(field, values) ? matchedIndexes(field.options, values) : [];\n const freeText = values.length > 0 && matched.length === 0;\n const options = field.options.map((option, at) => {\n const selected = matched.includes(at);\n return option.selected === selected ? option : { ...option, selected };\n });\n const chosen = freeText ? [...values] : matched.map((at) => field.options[at]!.value);\n const valueEntry = choiceEntryOf(chosen);\n if (field.family === 'combobox') {\n return { ...field, options, valueEntry, value: chosen[0] ?? '' };\n }\n return { ...field, options, valueEntry, selectedValues: chosen };\n}\n\n/** How `/V` (or `/DV`) holds choice values: none, one string, or an array. */\nfunction choiceEntryOf(values: readonly string[]): FormValueEntry {\n if (values.length === 0) return none();\n return values.length === 1 ? scalar(values[0]!) : { kind: 'array', values: [...values] };\n}\n\n/** `values` that are option values, in option order. */\nfunction inOptionOrder(options: readonly FormFieldOption[], values: readonly string[]): string[] {\n return matchedIndexes(options, values).map((at) => options[at]!.value);\n}\n\n/** A choice field with new options: what is still an option stays selected, and stays its default. */\nfunction withOptions<C extends Coordinates>(\n field: Extract<FormFieldDTO<C>, { family: 'combobox' | 'listbox' }>,\n options: FormFieldOption[],\n): FormFieldDTO<C> {\n const exports = options.map((option) => option.value);\n const keepsFreeText = field.family === 'combobox' && field.edit;\n const current =\n field.family === 'combobox' ? (field.value === '' ? [] : [field.value]) : field.selectedValues;\n const kept = keptValues(current, exports, keepsFreeText);\n // A list box's top row stays among its options.\n const listed =\n field.family === 'listbox'\n ? { ...field, options, topIndex: topRowOf(field.topIndex, options) }\n : { ...field, options };\n const reselected = choiceFieldWith(listed, kept);\n const defaults = valuesOfEntry(field.defaultValueEntry);\n if (field.defaultValueEntry.kind === 'none') return reselected;\n const keptDefaults = keptValues(defaults, exports, keepsFreeText);\n return withDefault(\n reselected as Extract<FormFieldDTO<C>, { family: 'combobox' | 'listbox' }>,\n keptDefaults,\n true,\n );\n}\n\n/** A list box's top row: an option's position, the last one past the end. */\nexport function topRowOf(topIndex: number, options: readonly unknown[]): number {\n return Math.max(0, Math.min(topIndex, options.length - 1));\n}\n\n/** The values still among `exports`; free text survives when nothing else does. */\nfunction keptValues(\n values: readonly string[],\n exports: readonly string[],\n keepFreeText: boolean,\n): string[] {\n const kept = values.filter((value) => exports.includes(value));\n return kept.length === 0 && keepFreeText && values.length > 0 ? [...values] : kept;\n}\n\n/**\n * A choice field's default set to `values` (option order; a dropdown's free\n * text as it is). `filtered`: what new options left of the old default,\n * where none left is an empty default rather than no default.\n */\nfunction withDefault<C extends Coordinates>(\n field: Extract<FormFieldDTO<C>, { family: 'combobox' | 'listbox' }>,\n values: readonly string[],\n filtered = false,\n): FormFieldDTO<C> {\n if (values.length === 0) {\n const entry: FormValueEntry = !filtered\n ? none()\n : field.family === 'listbox' && field.multiSelect\n ? { kind: 'array', values: [] }\n : scalar('');\n return field.family === 'combobox'\n ? { ...field, defaultValueEntry: entry, defaultValue: '' }\n : { ...field, defaultValueEntry: entry, defaultValue: [] };\n }\n const matched = choiceMatches(field, values);\n const ordered = matched ? inOptionOrder(field.options, values) : [...values];\n const entry = matched ? choiceEntryOf(ordered) : scalar(values[0]!);\n return field.family === 'combobox'\n ? { ...field, defaultValueEntry: entry, defaultValue: ordered[0] ?? '' }\n : { ...field, defaultValueEntry: entry, defaultValue: ordered };\n}\n\nfunction valuesOfEntry(entry: FormValueEntry): string[] {\n if (entry.kind === 'scalar') return [entry.value];\n if (entry.kind === 'array') return [...entry.values];\n return [];\n}\n\n/** A new widget's row: its placement and look, and what attaching it to the field gives it. */\nfunction widgetRowOfPlacement(\n draft: FormFieldDraft,\n placement: WidgetPlacement,\n at: { ref: AnnotationRef; field: number; nm: string | undefined },\n): WidgetAnnotation {\n const { page: _page, exportValue: _exportValue, ...look } = placement;\n const row = annotationOfDraft(\n { subtype: 'widget', ...look } as Parameters<typeof annotationOfDraft>[0],\n { ref: at.ref, ...(at.nm !== undefined ? { nm: at.nm } : {}) },\n ) as WidgetAnnotation;\n const toggle = draft.family === 'checkbox' || draft.family === 'radio';\n return {\n ...row,\n rect: standingRectOf(row.box, row.rotation),\n field: { kind: 'objectNumber', objectNumber: at.field },\n fieldFamily: draft.family,\n // Attaching the widget prints it and draws its appearance (a signature\n // field's waits for its signature); a checkbox or radio button starts off.\n print: true,\n hasAppearance: draft.family !== 'signature',\n appearanceState: toggle ? 'Off' : null,\n caption: draft.family === 'pushbutton' ? (placement.caption ?? null) : null,\n } as WidgetAnnotation;\n}\n\nfunction toggleWidgetOf(widget: FormFieldWidget, exportValue: string): ToggleFieldWidget {\n return { ...widget, onState: exportValue, exportValue, checked: false };\n}\n\nconst optionOf = (input: FormFieldOptionInput): FormFieldOption => ({\n label: input.label,\n value: input.value,\n selected: false,\n});\n\nconst objectNumberOf = (ref: AnnotationRef | Annotation['ref']): number =>\n ref.kind === 'objectNumber' ? ref.objectNumber : 0;\n\nconst scalar = (value: string): FormValueEntry => ({ kind: 'scalar', value });\nconst none = (): FormValueEntry => ({ kind: 'none' });\n\nfunction notReset(field: FormFieldDTO<Coordinates>): EngineError {\n return new EngineError(EngineErrorCode.Unknown, `'${field.name}' could not be reset`);\n}\n","import type { FormFieldValue } from './value';\nimport type { FormFieldRef } from '../identity/FormFieldRef';\nimport type { ChangeOp } from '../mutation/Change';\n\nexport type FormFieldDisplay = 'visible' | 'hidden' | 'noPrint' | 'noView';\n\n/** Ordered, committed outputs of one client-side form script run. */\nexport type FormEffect =\n | { kind: 'setValue'; ref: FormFieldRef; value: FormFieldValue }\n | { kind: 'setDisplay'; ref: FormFieldRef; display: FormFieldDisplay }\n | { kind: 'setAppearanceText'; ref: FormFieldRef; text: string }\n | { kind: 'reset'; refs: FormFieldRef[] };\n\n/**\n * A script run's effects as the ops of one change, in their order: what a\n * form commit sends with `doc.apply`, all or nothing.\n */\nexport function formEffectOps(effects: readonly FormEffect[]): ChangeOp[] {\n return effects.map((effect): ChangeOp => {\n switch (effect.kind) {\n case 'setValue':\n return { type: 'forms.setValue', field: effect.ref, value: effect.value };\n case 'setDisplay':\n return { type: 'forms.setDisplay', field: effect.ref, display: effect.display };\n case 'setAppearanceText':\n return { type: 'forms.setAppearanceText', field: effect.ref, text: effect.text };\n case 'reset':\n return { type: 'forms.reset', fields: effect.refs };\n }\n });\n}\n","import type { AnnotationListMutationMeta } from './AnnotationListMutationMeta';\nimport type {\n AnnotationCreateResult,\n AnnotationDeleteResult,\n AnnotationReorderResult,\n AnnotationUpdateResult,\n} from './AnnotationMutationResults';\nimport type { CustomMetadataUpdateResult } from './CustomMetadataUpdateResult';\nimport type {\n FormCalculationsReorderResult,\n FormFieldCreateResult,\n FormFieldDeleteResult,\n FormFieldUpdateResult,\n FormMutationMeta,\n FormResetResult,\n FormSetValueResult,\n FormWidgetDeleteResult,\n FormWidgetLinkResult,\n FormWidgetRestoreResult,\n FormWidgetsReorderResult,\n FormWidgetUpdateResult,\n} from './FormMutationResults';\nimport type { AnnotationPosition, FieldPosition } from './ListPosition';\nimport type { MetadataUpdateResult } from './MetadataUpdateResult';\nimport type { MutationMeta } from './MutationMeta';\nimport type { Annotation, AnnotationDraft, AnnotationPatch } from '../annotation/kinds';\nimport type { WidgetAnnotation, WidgetPatch } from '../annotation/kinds/widget';\nimport type { AnnotationActor } from '../auth/scope/types';\nimport {\n annotationResourceBuffers,\n hasAnnotationResources,\n resolveAnnotationResources,\n withFileFromResource,\n type AnnotationResources,\n type WireAnnotationResources,\n} from '../annotation/resources';\nimport type { CustomMetadataPatch } from '../dto/CustomMetadataPatch';\nimport type { MetadataPatch } from '../dto/MetadataPatch';\nimport type { SerializedEngineError } from '../errors/EngineError';\nimport type { FormFieldDraft, WidgetPlacement } from '../forms/draft';\nimport type { FormFieldDisplay } from '../forms/effects';\nimport type { FormFieldDTO } from '../forms/field';\nimport type { FormFieldPatch } from '../forms/patch';\nimport type { FormFieldValue } from '../forms/value';\nimport type { AnnotationRef } from '../identity/AnnotationRef';\nimport type { FormFieldRef } from '../identity/FormFieldRef';\nimport type { PageRef } from '../identity/PageRef';\nimport type { Coordinates, PageCoordinates } from '../pageSpace/coordinates';\nimport type { SignatureAppearanceInput } from '../signature/types';\nimport type { WireAnnotationBundle } from '../transfer/AnnotationBundle';\nimport type { AnnotationImportResult } from '../transfer/annotationImport';\nimport type { WireFormBundle } from '../transfer/FormBundle';\nimport type { FormImportResult, FormValuesImportResult } from '../transfer/formImport';\nimport type { BundleImportPages } from '../transfer/bundle';\nimport type { BundleLimits } from '../transfer/bundleLimits';\n\n/**\n * One user action, applied as one transaction (`doc.apply`): its ops in\n * order, all of them or none; or the reverse of an earlier change.\n *\n * A change is one entry everywhere: one audit row, one burst of events that\n * share `origin.tx`, and one undo step. `R` is how resources travel: what a\n * caller passes (`AnnotationResources`), or bytes on the wire.\n */\nexport type Change<C extends Coordinates = PageCoordinates, R = AnnotationResources> =\n | { readonly ops: readonly ChangeOp<C, R>[] }\n /**\n * The reverse of the change this names (its `opId`), as the engine\n * recorded it when that change ran. It applies where the document still\n * shows what that change set, and lists what it left alone (`skipped`).\n */\n | { readonly undoOf: string };\n\n/**\n * One op of a change: exactly the parameters of its single verb. A create\n * that names its object number (from `doc.objectNumbers`) can be referred to\n * by later ops of the same change, by its final ref.\n *\n * `expect` says what the op assumes the document holds now, in the shape of\n * what it writes: an update's `expect` is a patch of the values the fields\n * must have. When the document doesn't match, the whole change is refused\n * with `ChangeConflict`. Without it, the last write wins.\n * A reorder takes none: its position names a neighbour, so it keeps its\n * meaning when other rows came and went.\n */\nexport type ChangeOp<C extends Coordinates = PageCoordinates, R = AnnotationResources> =\n | {\n readonly type: 'annotations.create';\n readonly page: PageRef;\n readonly data: AnnotationDraft<C>;\n readonly objectNumber?: number;\n readonly resources?: R;\n }\n | {\n readonly type: 'annotations.update';\n readonly ref: AnnotationRef;\n readonly patch: AnnotationPatch<C>;\n readonly resources?: R;\n readonly expect?: AnnotationPatch<C>;\n }\n | {\n readonly type: 'annotations.delete';\n readonly ref: AnnotationRef;\n readonly expect?: AnnotationPatch<C>;\n }\n | {\n /** Stacking order: the annotations go together to `position` among the page's annotations. */\n readonly type: 'annotations.reorder';\n readonly page: PageRef;\n readonly refs: readonly AnnotationRef[];\n readonly position: AnnotationPosition;\n }\n | {\n readonly type: 'forms.setValue';\n readonly field: FormFieldRef;\n readonly value: FormFieldValue;\n readonly expect?: FormFieldValue;\n }\n | {\n readonly type: 'forms.setDisplay';\n readonly field: FormFieldRef;\n readonly display: FormFieldDisplay;\n }\n | {\n readonly type: 'forms.setAppearanceText';\n readonly field: FormFieldRef;\n readonly text: string;\n }\n | {\n readonly type: 'forms.reset';\n /** The fields to reset; every field without it. */\n readonly fields?: readonly FormFieldRef[];\n }\n | {\n readonly type: 'forms.create';\n readonly draft: FormFieldDraft<C>;\n readonly objectNumber?: number;\n /** The object numbers its widgets get, in `draft.widgets` order. */\n readonly widgetObjectNumbers?: readonly number[];\n }\n | {\n readonly type: 'forms.update';\n readonly field: FormFieldRef;\n readonly patch: FormFieldPatch;\n readonly expect?: FormFieldPatch;\n }\n | {\n readonly type: 'forms.delete';\n readonly field: FormFieldRef;\n readonly expect?: FormFieldPatch;\n }\n | {\n readonly type: 'forms.addWidget';\n readonly field: FormFieldRef;\n readonly placement: WidgetPlacement<C>;\n readonly objectNumber?: number;\n /** The number the widget split off a merged field gets, when the field is merged. */\n readonly splitObjectNumber?: number;\n }\n | {\n readonly type: 'forms.removeWidget';\n readonly field: FormFieldRef;\n readonly widget: AnnotationRef;\n }\n | {\n /** The widget leaves its page, and its field when it has one. */\n readonly type: 'forms.deleteWidget';\n readonly widget: AnnotationRef;\n readonly expect?: WidgetPatch<C>;\n }\n | {\n /** The calculation order: the fields go together to `position` in it. */\n readonly type: 'forms.reorderCalculations';\n readonly fields: readonly FormFieldRef[];\n readonly position: FieldPosition;\n }\n | {\n /** Stacking order: the widgets go together to `position` among the page's widgets. */\n readonly type: 'forms.reorderWidgets';\n readonly page: PageRef;\n readonly widgets: readonly AnnotationRef[];\n readonly position: AnnotationPosition;\n }\n | {\n /** A widget's place and look: what `annotations.update` takes for a widget. */\n readonly type: 'forms.updateWidget';\n readonly widget: AnnotationRef;\n readonly patch: WidgetPatch<C>;\n readonly expect?: WidgetPatch<C>;\n }\n | {\n readonly type: 'forms.setSignatureAppearance';\n readonly field: FormFieldRef;\n readonly appearance: SignatureAppearanceInput;\n }\n | {\n readonly type: 'metadata.update';\n readonly patch: MetadataPatch;\n readonly expect?: MetadataPatch;\n }\n | {\n readonly type: 'metadata.updateCustom';\n readonly patch: CustomMetadataPatch;\n };\n\n/**\n * An import, as the one op of its change: `doc.annotations.import` runs it,\n * so the import is kept under its `opId` with the record that undoes it,\n * like any change. Only the import verb makes one: `doc.apply` takes no\n * import, so writing restored attribution stays the import's.\n */\nexport interface AnnotationImportOp {\n readonly type: 'annotations.import';\n /** In page space, its resources as bytes. */\n readonly bundle: WireAnnotationBundle;\n readonly pages?: BundleImportPages;\n readonly attribution: 'restore' | 'stamp';\n /**\n * Who `'stamp'` attributes each annotation to, as a create does, and whose\n * user `'restore'` records as `importedBy`.\n */\n readonly actor?: AnnotationActor;\n readonly limits: BundleLimits;\n}\n\n/**\n * A form import, as the one op of its change: `doc.forms.import` (the\n * design) or `doc.forms.importValues` (the values). Like an annotation\n * import, only its verb makes one.\n */\nexport interface FormImportOp {\n readonly type: 'forms.import' | 'forms.importValues';\n /** In page space, its resources as bytes. */\n readonly bundle: WireFormBundle;\n /** A design import's: where each page of the bundle goes. */\n readonly pages?: BundleImportPages;\n readonly attribution: 'restore' | 'stamp';\n /** A design import's: whether each field gets the bundle's value. */\n readonly values?: boolean;\n /**\n * Whom `'stamp'` makes the creator and filler, as `create` and `setValue`\n * do, and whose user `'restore'` records as `importedBy`.\n */\n readonly actor?: AnnotationActor;\n readonly limits: BundleLimits;\n /**\n * A design import's: whether the caller holds `doc.forms.script`, which\n * the verb checked. Without it, scripts, submits and links are left out.\n */\n readonly mayScript?: boolean;\n}\n\n/** An op of a change the engine runs and records: one `doc.apply` takes, or an import. */\nexport type RecordedOp<C extends Coordinates = PageCoordinates, R = AnnotationResources> =\n | ChangeOp<C, R>\n | AnnotationImportOp\n | FormImportOp;\n\n/** A change as the engine runs and records it: its ops, an import among them, or an undo. */\nexport type RecordedChange<C extends Coordinates = PageCoordinates, R = AnnotationResources> =\n | { readonly ops: readonly RecordedOp<C, R>[] }\n | { readonly undoOf: string };\n\n/** What an item can be: an op's type, an import's, or a restore (only in an undo). */\nexport type ChangeItemType =\n | RecordedOp['type']\n | 'annotations.restore'\n | 'forms.restore'\n | 'forms.restoreWidget';\n\n/**\n * An op an undo left alone entirely: the document no longer showed what the\n * change being undone had set (someone changed it since, replied to it, or\n * deleted it), so nothing was written and no event published. `op` is the\n * item it would have been.\n */\nexport interface SkippedChangeItem {\n type: 'skipped';\n op: ChangeItemType;\n meta: MutationMeta;\n}\n\n/**\n * What one op did: its single verb's result, with the op's `type`; or, in an\n * undo, an op it left alone (`SkippedChangeItem`). An undo's update items list\n * in `skipped` the fields they left alone, and its restore items name what\n * came back.\n */\nexport type ChangeItem<C extends Coordinates = PageCoordinates> =\n | ({ type: 'annotations.create'; page: PageRef } & AnnotationCreateResult<C>)\n | ({\n type: 'annotations.update';\n page: PageRef;\n /** The fields an undo left alone: they no longer showed what the change had set. */\n skipped?: readonly string[];\n } & AnnotationUpdateResult<C>)\n | ({ type: 'annotations.delete'; page: PageRef } & AnnotationDeleteResult)\n | ({ type: 'annotations.reorder'; page: PageRef } & AnnotationReorderResult)\n /** An import's answer: only `doc.annotations.import` answers one. */\n | ({ type: 'annotations.import' } & AnnotationImportResult<C>)\n /** A form import's answer: only `doc.forms.import` and `doc.forms.importValues` answer one. */\n | ({ type: 'forms.import' } & FormImportResult<C>)\n | ({ type: 'forms.importValues' } & FormValuesImportResult<C>)\n | {\n type: 'annotations.restore';\n page: PageRef;\n /** What came back, in `/Annots` order: the annotation first, then what went with it. */\n annotations: Annotation<C>[];\n meta: AnnotationListMutationMeta;\n }\n | ({ type: 'forms.setValue' } & FormSetValueResult<C>)\n | ({ type: 'forms.setDisplay' } & FormFieldUpdateResult<C>)\n | ({ type: 'forms.setAppearanceText' } & FormFieldUpdateResult<C>)\n | ({\n type: 'forms.reset';\n /** The fields an undo left alone, by name. */\n skipped?: readonly string[];\n } & FormResetResult<C>)\n | ({ type: 'forms.create' } & FormFieldCreateResult<C>)\n | ({\n type: 'forms.update';\n /** The properties an undo left alone: they no longer showed what the change had set. */\n skipped?: readonly string[];\n } & FormFieldUpdateResult<C>)\n | ({ type: 'forms.delete' } & FormFieldDeleteResult)\n | {\n type: 'forms.restore';\n field: FormFieldDTO<C>;\n widgets: WidgetAnnotation<C>[];\n meta: FormMutationMeta;\n }\n | ({ type: 'forms.setSignatureAppearance' } & FormFieldUpdateResult<C>)\n | ({ type: 'forms.addWidget' } & FormWidgetLinkResult<C>)\n | ({ type: 'forms.removeWidget' } & FormWidgetLinkResult<C>)\n | ({ type: 'forms.deleteWidget' } & FormWidgetDeleteResult<C>)\n | ({ type: 'forms.restoreWidget' } & FormWidgetRestoreResult<C>)\n | ({ type: 'forms.reorderWidgets' } & FormWidgetsReorderResult)\n | ({ type: 'forms.reorderCalculations' } & FormCalculationsReorderResult)\n | ({\n type: 'forms.updateWidget';\n /** The fields an undo left alone: they no longer showed what the change had set. */\n skipped?: readonly string[];\n } & FormWidgetUpdateResult<C>)\n | ({\n type: 'metadata.update';\n /** The entries an undo left alone. */\n skipped?: readonly string[];\n } & MetadataUpdateResult)\n | ({\n type: 'metadata.updateCustom';\n /** The keys an undo left alone. */\n skipped?: readonly string[];\n } & CustomMetadataUpdateResult)\n | SkippedChangeItem;\n\n/** Whether an item is an op an undo left alone entirely. */\nexport function isSkippedItem<C extends Coordinates>(\n item: ChangeItem<C>,\n): item is SkippedChangeItem {\n return item.type === 'skipped';\n}\n\n/**\n * Whether an item wrote to the document: not an op an undo left alone, nor\n * an import that left every row of its bundle out.\n */\nexport function itemWrote<C extends Coordinates>(item: ChangeItem<C>): boolean {\n switch (item.type) {\n case 'skipped':\n return false;\n case 'annotations.import':\n return item.annotations.length > 0;\n case 'forms.import':\n case 'forms.importValues':\n return item.fields.length > 0;\n default:\n return true;\n }\n}\n\n/** What `doc.apply` resolves. */\nexport interface ChangeResult<C extends Coordinates = PageCoordinates> {\n /** One per op, in op order; for an undo, one per op of the reverse. */\n items: ChangeItem<C>[];\n /**\n * Every page the change touched, the cloud's cache delta, the change's\n * `opId` (what `{ undoOf }` names) and whether it can be undone.\n */\n meta: MutationMeta;\n}\n\n/** Whether a change is an undo (`{ undoOf }`) rather than a list of ops. */\nexport function isUndoChange<C extends Coordinates, R>(\n change: RecordedChange<C, R>,\n): change is { readonly undoOf: string } {\n return 'undoOf' in change;\n}\n\n/**\n * One change's answer from the server (`POST …/changes`): applied with its\n * result, or refused with the error. A change asked again gets the same\n * answer.\n */\nexport type ChangeAnswer =\n | { readonly opId: string; readonly status: 'applied'; readonly result: ChangeResult }\n | { readonly opId: string; readonly status: 'refused'; readonly error: SerializedEngineError };\n\n/**\n * The object numbers a change's creates name: each must be one its editing\n * session holds. An undo names none; what it restores keeps its numbers.\n */\nexport function objectNumbersNamedBy<C extends Coordinates, R>(\n change: RecordedChange<C, R>,\n): number[] {\n if (isUndoChange(change)) return [];\n const named: number[] = [];\n for (const op of change.ops) {\n switch (op.type) {\n case 'annotations.create':\n if (op.objectNumber !== undefined) named.push(op.objectNumber);\n break;\n case 'forms.create':\n if (op.objectNumber !== undefined) named.push(op.objectNumber);\n named.push(...(op.widgetObjectNumbers ?? []));\n break;\n case 'forms.addWidget':\n if (op.objectNumber !== undefined) named.push(op.objectNumber);\n if (op.splitObjectNumber !== undefined) named.push(op.splitObjectNumber);\n break;\n default:\n break;\n }\n }\n return named;\n}\n\n/**\n * The object numbers a change's ops refer to: every `{ kind: 'objectNumber' }`\n * ref anywhere in them, the annotation or field an op writes and the parent\n * a reply names among them. A change that refers to a number only a refused\n * change creates can't apply. An undo refers to none: it names its change.\n */\nexport function objectNumbersReferencedBy<C extends Coordinates, R>(\n change: RecordedChange<C, R>,\n): number[] {\n if (isUndoChange(change)) return [];\n const referenced = new Set<number>();\n const visit = (value: unknown): void => {\n if (Array.isArray(value)) {\n value.forEach(visit);\n return;\n }\n if (value === null || typeof value !== 'object' || ArrayBuffer.isView(value)) return;\n const record = value as Record<string, unknown>;\n if (record.kind === 'objectNumber' && typeof record.objectNumber === 'number') {\n referenced.add(record.objectNumber);\n }\n for (const field of Object.values(record)) visit(field);\n };\n change.ops.forEach(visit);\n return [...referenced];\n}\n\n/**\n * A change with bytes it owns, ready to send: each op's resources copied\n * (`resolveAnnotationResources`), a file attachment's `file` completed from\n * its `File` (`withFileFromResource`), a signature appearance copied.\n * `buffers` lists every copy, for a worker's transfer list. The caller's\n * bytes are only read.\n */\nexport async function resolveChangeResources(change: Change): Promise<{\n change: Change<PageCoordinates, WireAnnotationResources>;\n buffers: ArrayBuffer[];\n}> {\n if (isUndoChange(change)) return { change, buffers: [] };\n const buffers: ArrayBuffer[] = [];\n const ops: ChangeOp<PageCoordinates, WireAnnotationResources>[] = [];\n for (const op of change.ops) {\n switch (op.type) {\n case 'annotations.create': {\n const { resources, ...rest } = op;\n const wire = await resolveAnnotationResources(resources);\n buffers.push(...annotationResourceBuffers(wire));\n ops.push({\n ...rest,\n data: withFileFromResource(op.data, resources),\n ...(hasAnnotationResources(wire) ? { resources: wire } : {}),\n });\n break;\n }\n case 'annotations.update': {\n const { resources, ...rest } = op;\n const wire = await resolveAnnotationResources(resources);\n buffers.push(...annotationResourceBuffers(wire));\n ops.push({ ...rest, ...(hasAnnotationResources(wire) ? { resources: wire } : {}) });\n break;\n }\n case 'forms.setSignatureAppearance': {\n const pdf = op.appearance.pdf.slice();\n buffers.push(pdf.buffer);\n ops.push({ ...op, appearance: { pdf } });\n break;\n }\n default:\n ops.push(op);\n }\n }\n return { change: { ops }, buffers };\n}\n"],"mappings":"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"}
@@ -0,0 +1,120 @@
1
+ const require_format = require("./format-Bp3QFSH1.cjs");
2
+ const require_LocalDocumentHandle = require("./LocalDocumentHandle-D02FMm-Z.cjs");
3
+ //#region src/engine/LocalEngine.ts
4
+ /** Whether `engine` is the local engine, with its fonts and `warmup()`. */
5
+ function isLocalEngine(engine) {
6
+ return require_LocalDocumentHandle.hasLocalEngineBrand(engine);
7
+ }
8
+ //#endregion
9
+ //#region src/engine/DocumentRenderService.ts
10
+ const CONTINUOUS_RENDER_POLICY = { kind: "continuous" };
11
+ /**
12
+ * Conform a full-page viewport to a render policy — the one snap
13
+ * implementation, shared by every engine and plugin. Pure and explicit
14
+ * by design:
15
+ *
16
+ * - `continuous` → identity (local/cloud plugin code stays byte-identical).
17
+ * - `lattice` → returns a `width`-kind viewport at the smallest ladder
18
+ * width ≥ the requested detail (snap up: always crisp, CSS downscales
19
+ * for free), capped at the largest width — detail beyond the cap is the
20
+ * tile pyramid's job, by design.
21
+ * - `scale`-kind requests convert through the page's width in PDF user
22
+ * units — pass `opts.pageWidth` (the caller has it from the layout);
23
+ * omitting it for a scale viewport under a lattice policy is a
24
+ * programmer error and throws `InvalidArg`.
25
+ */
26
+ function snapFullPageViewport(policy, viewport, opts) {
27
+ if (policy.kind === "continuous") return viewport;
28
+ if (policy.fullPage.widths.length === 0) throw new require_format.EngineError(require_format.EngineErrorCode.InvalidArg, "render policy has an empty width ladder");
29
+ const widths = [...policy.fullPage.widths].sort((a, b) => a - b);
30
+ let requested;
31
+ if (viewport.kind === "width") requested = viewport.width;
32
+ else {
33
+ const pageWidth = opts?.pageWidth;
34
+ if (pageWidth === void 0 || pageWidth <= 0) throw new require_format.EngineError(require_format.EngineErrorCode.InvalidArg, "snapping a scale viewport to a width lattice requires opts.pageWidth");
35
+ requested = (viewport.scale ?? 1) * pageWidth;
36
+ }
37
+ return {
38
+ kind: "width",
39
+ width: widths.find((width) => width >= requested) ?? widths[widths.length - 1]
40
+ };
41
+ }
42
+ /**
43
+ * Conform an annotation-appearance scale to the policy's appearance
44
+ * lattice. Same discipline as {@link snapFullPageViewport}: identity on
45
+ * continuous (and when the policy carries no appearance block), snap up,
46
+ * cap at the largest point. Callers derive `scale` from the page's
47
+ * effective render scale (`snappedWidth / pageWidth`, × devicePixelRatio
48
+ * as needed) so composites stay crisp against the page raster.
49
+ */
50
+ function snapAppearanceScale(policy, scale) {
51
+ if (policy.kind === "continuous" || policy.appearances === void 0) return scale;
52
+ if (policy.appearances.scales.length === 0) throw new require_format.EngineError(require_format.EngineErrorCode.InvalidArg, "render policy has an empty appearance-scale lattice");
53
+ const scales = [...policy.appearances.scales].sort((a, b) => a - b);
54
+ return scales.find((s) => s >= scale) ?? scales[scales.length - 1];
55
+ }
56
+ /**
57
+ * The scale an appearance render's viewport puts on the appearance lattice:
58
+ * a `scale` viewport's scale (1 when omitted), and `undefined` for a
59
+ * `width` viewport, whose scale depends on the page's size and so is never
60
+ * on the lattice.
61
+ */
62
+ function appearanceLatticeScale(viewport) {
63
+ if (viewport === void 0) return 1;
64
+ return viewport.kind === "scale" ? viewport.scale ?? 1 : void 0;
65
+ }
66
+ /**
67
+ * Conform a tile-pyramid scale to the policy's tile lattice — the third
68
+ * member of the `snap<PolicyBlock><Quantity>` family. Identity on
69
+ * continuous and while the deployment doesn't advertise a `tiles` block
70
+ * (the block is reserved until the deep-zoom vertical ships server-side;
71
+ * the tiling client uses its own default pyramid then — see
72
+ * plugin-render). Snap up, cap at the largest scale: per-tile cost is
73
+ * constant by construction (`tileSize²` pixels regardless of level), so
74
+ * the cap bounds artifact count, not memory.
75
+ */
76
+ function snapTileScale(policy, scale) {
77
+ if (policy.kind === "continuous" || policy.tiles === void 0) return scale;
78
+ if (policy.tiles.scales.length === 0) throw new require_format.EngineError(require_format.EngineErrorCode.InvalidArg, "render policy has an empty tile-scale lattice");
79
+ const scales = [...policy.tiles.scales].sort((a, b) => a - b);
80
+ return scales.find((s) => s >= scale) ?? scales[scales.length - 1];
81
+ }
82
+ //#endregion
83
+ Object.defineProperty(exports, "CONTINUOUS_RENDER_POLICY", {
84
+ enumerable: true,
85
+ get: function() {
86
+ return CONTINUOUS_RENDER_POLICY;
87
+ }
88
+ });
89
+ Object.defineProperty(exports, "appearanceLatticeScale", {
90
+ enumerable: true,
91
+ get: function() {
92
+ return appearanceLatticeScale;
93
+ }
94
+ });
95
+ Object.defineProperty(exports, "isLocalEngine", {
96
+ enumerable: true,
97
+ get: function() {
98
+ return isLocalEngine;
99
+ }
100
+ });
101
+ Object.defineProperty(exports, "snapAppearanceScale", {
102
+ enumerable: true,
103
+ get: function() {
104
+ return snapAppearanceScale;
105
+ }
106
+ });
107
+ Object.defineProperty(exports, "snapFullPageViewport", {
108
+ enumerable: true,
109
+ get: function() {
110
+ return snapFullPageViewport;
111
+ }
112
+ });
113
+ Object.defineProperty(exports, "snapTileScale", {
114
+ enumerable: true,
115
+ get: function() {
116
+ return snapTileScale;
117
+ }
118
+ });
119
+
120
+ //# sourceMappingURL=DocumentRenderService-BfFdFSwI.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DocumentRenderService-BfFdFSwI.cjs","names":["hasLocalEngineBrand","EngineError","EngineErrorCode"],"sources":["../src/engine/LocalEngine.ts","../src/engine/DocumentRenderService.ts"],"sourcesContent":["import type { Engine } from './Engine';\nimport type { FontService } from './FontService';\nimport type { LocalDocumentHandle } from './LocalDocumentHandle';\nimport { hasLocalEngineBrand } from './localEngineBrand';\nimport type { OpenInput, OpenOptions } from '../dto/OpenInput';\nimport { AbortablePromise } from '../promise/AbortablePromise';\n\n/**\n * The engine that runs PDFium itself, in the browser or in Node: the shared\n * {@link Engine} and what only it can do. `localEngine()` returns one, so an\n * app built on it reaches these without a check; code that takes any engine\n * checks with {@link isLocalEngine}.\n */\nexport interface LocalEngine extends Engine {\n open(input: OpenInput, options?: OpenOptions): AbortablePromise<LocalDocumentHandle>;\n\n /**\n * Start booting the engine (Worker spawn, WASM compile) without doing any\n * work. Idempotent and non-blocking: the engine boots on first use anyway,\n * so this only overlaps that boot with the app's own start.\n */\n warmup(): void;\n\n /** Runtime font registration and fallback fonts. See {@link FontService}. */\n readonly fonts: FontService;\n}\n\n/** Whether `engine` is the local engine, with its fonts and `warmup()`. */\nexport function isLocalEngine(engine: Engine): engine is LocalEngine {\n return hasLocalEngineBrand(engine);\n}\n","import { EngineError } from '../errors/EngineError';\nimport { EngineErrorCode } from '../errors/EngineErrorCode';\nimport type { PageRenderViewport } from '../dto/PageRender';\nimport type { AbortablePromise } from '../promise/AbortablePromise';\n\n/**\n * The engine's render-parameter policy.\n *\n * - `continuous` — any viewport renders exactly as requested. The local\n * engine always answers this: rendering is in-process, there is no\n * shared cache to protect, and exactness is the local product promise.\n * - `lattice` — the deployment treats a finite set of render points as\n * durable, CDN-shared artifacts. The bounded quantity\n * is output pixels, never zoom:\n *\n * - `fullPage.widths` — full-page renders quantize on `viewport.width`\n * (a scale lattice bounds artifact count but not size: PDF page space\n * is effectively unbounded, so scale 1 of a poster page is a memory\n * bomb while width caps the dominant dimension by construction).\n * - `tiles` — reserved for the deep-zoom vertical: a scale-based\n * pyramid × fixed tile size, where per-job cost is constant. Absent\n * until the tiling plugin ships; reserving the shape keeps the SDK\n * contract from churning twice.\n * - `maxRenderPixels` — the worker-side output budget for degenerate\n * geometry (width bounds width, not height).\n *\n * The SDK never conforms a request implicitly — the same `render.image`\n * call must not return different pixels on local vs cloud. Conformance is\n * the caller's visible choice via {@link snapFullPageViewport}.\n */\nexport type EngineRenderPolicy =\n | { readonly kind: 'continuous' }\n | {\n readonly kind: 'lattice';\n readonly fullPage: { readonly widths: readonly number[] };\n readonly tiles?: {\n readonly tileSizes: readonly number[];\n readonly scales: readonly number[];\n };\n /**\n * Annotation-appearance lattice — scale-based, unlike full pages:\n * an appearance is sized by `annotation.rect × scale`, rects span\n * orders of magnitude (a 4pt caret vs a page-sized stamp), and the\n * composite must track the page's effective render scale or\n * annotations sit blurry on a crisp raster. Small images → the\n * ladder affords finer, taller steps than pages ever could.\n */\n readonly appearances?: { readonly scales: readonly number[] };\n readonly maxRenderPixels?: number;\n readonly formats: readonly ('webp' | 'png')[];\n readonly background: 'white';\n readonly enforced: boolean;\n };\n\nexport const CONTINUOUS_RENDER_POLICY: EngineRenderPolicy = { kind: 'continuous' };\n\n/**\n * Document-scoped render policy surface (`doc.render`). Async because the\n * cloud engine learns its policy from `/v1/access`; the local engine\n * resolves immediately with `continuous`.\n *\n * Per-page rendering itself stays on `page(pon).render` — this service\n * carries policy, not pixels.\n */\nexport interface DocumentRenderService {\n getPolicy(): AbortablePromise<EngineRenderPolicy>;\n}\n\n/**\n * Conform a full-page viewport to a render policy — the one snap\n * implementation, shared by every engine and plugin. Pure and explicit\n * by design:\n *\n * - `continuous` → identity (local/cloud plugin code stays byte-identical).\n * - `lattice` → returns a `width`-kind viewport at the smallest ladder\n * width ≥ the requested detail (snap up: always crisp, CSS downscales\n * for free), capped at the largest width — detail beyond the cap is the\n * tile pyramid's job, by design.\n * - `scale`-kind requests convert through the page's width in PDF user\n * units — pass `opts.pageWidth` (the caller has it from the layout);\n * omitting it for a scale viewport under a lattice policy is a\n * programmer error and throws `InvalidArg`.\n */\nexport function snapFullPageViewport(\n policy: EngineRenderPolicy,\n viewport: PageRenderViewport,\n opts?: { pageWidth?: number },\n): PageRenderViewport {\n if (policy.kind === 'continuous') return viewport;\n if (policy.fullPage.widths.length === 0) {\n throw new EngineError(EngineErrorCode.InvalidArg, 'render policy has an empty width ladder');\n }\n const widths = [...policy.fullPage.widths].sort((a, b) => a - b);\n\n let requested: number;\n if (viewport.kind === 'width') {\n requested = viewport.width;\n } else {\n const pageWidth = opts?.pageWidth;\n if (pageWidth === undefined || pageWidth <= 0) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n 'snapping a scale viewport to a width lattice requires opts.pageWidth',\n );\n }\n requested = (viewport.scale ?? 1) * pageWidth;\n }\n\n const snapped = widths.find((width) => width >= requested) ?? widths[widths.length - 1]!;\n return { kind: 'width', width: snapped };\n}\n\n/**\n * Conform an annotation-appearance scale to the policy's appearance\n * lattice. Same discipline as {@link snapFullPageViewport}: identity on\n * continuous (and when the policy carries no appearance block), snap up,\n * cap at the largest point. Callers derive `scale` from the page's\n * effective render scale (`snappedWidth / pageWidth`, × devicePixelRatio\n * as needed) so composites stay crisp against the page raster.\n */\nexport function snapAppearanceScale(policy: EngineRenderPolicy, scale: number): number {\n if (policy.kind === 'continuous' || policy.appearances === undefined) return scale;\n if (policy.appearances.scales.length === 0) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n 'render policy has an empty appearance-scale lattice',\n );\n }\n const scales = [...policy.appearances.scales].sort((a, b) => a - b);\n return scales.find((s) => s >= scale) ?? scales[scales.length - 1]!;\n}\n\n/**\n * The scale an appearance render's viewport puts on the appearance lattice:\n * a `scale` viewport's scale (1 when omitted), and `undefined` for a\n * `width` viewport, whose scale depends on the page's size and so is never\n * on the lattice.\n */\nexport function appearanceLatticeScale(\n viewport: PageRenderViewport | undefined,\n): number | undefined {\n if (viewport === undefined) return 1;\n return viewport.kind === 'scale' ? (viewport.scale ?? 1) : undefined;\n}\n\n/**\n * Conform a tile-pyramid scale to the policy's tile lattice — the third\n * member of the `snap<PolicyBlock><Quantity>` family. Identity on\n * continuous and while the deployment doesn't advertise a `tiles` block\n * (the block is reserved until the deep-zoom vertical ships server-side;\n * the tiling client uses its own default pyramid then — see\n * plugin-render). Snap up, cap at the largest scale: per-tile cost is\n * constant by construction (`tileSize²` pixels regardless of level), so\n * the cap bounds artifact count, not memory.\n */\nexport function snapTileScale(policy: EngineRenderPolicy, scale: number): number {\n if (policy.kind === 'continuous' || policy.tiles === undefined) return scale;\n if (policy.tiles.scales.length === 0) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n 'render policy has an empty tile-scale lattice',\n );\n }\n const scales = [...policy.tiles.scales].sort((a, b) => a - b);\n return scales.find((s) => s >= scale) ?? scales[scales.length - 1]!;\n}\n"],"mappings":";;;;AA4BA,SAAgB,cAAc,QAAuC;CACnE,OAAOA,4BAAAA,oBAAoB,MAAM;AACnC;;;ACwBA,MAAa,2BAA+C,EAAE,MAAM,aAAa;;;;;;;;;;;;;;;;AA6BjF,SAAgB,qBACd,QACA,UACA,MACoB;CACpB,IAAI,OAAO,SAAS,cAAc,OAAO;CACzC,IAAI,OAAO,SAAS,OAAO,WAAW,GACpC,MAAM,IAAIC,eAAAA,YAAYC,eAAAA,gBAAgB,YAAY,yCAAyC;CAE7F,MAAM,SAAS,CAAC,GAAG,OAAO,SAAS,MAAM,CAAC,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC;CAE/D,IAAI;CACJ,IAAI,SAAS,SAAS,SACpB,YAAY,SAAS;MAChB;EACL,MAAM,YAAY,MAAM;EACxB,IAAI,cAAc,KAAA,KAAa,aAAa,GAC1C,MAAM,IAAID,eAAAA,YACRC,eAAAA,gBAAgB,YAChB,sEACF;EAEF,aAAa,SAAS,SAAS,KAAK;CACtC;CAGA,OAAO;EAAE,MAAM;EAAS,OADR,OAAO,MAAM,UAAU,SAAS,SAAS,KAAK,OAAO,OAAO,SAAS;CAC9C;AACzC;;;;;;;;;AAUA,SAAgB,oBAAoB,QAA4B,OAAuB;CACrF,IAAI,OAAO,SAAS,gBAAgB,OAAO,gBAAgB,KAAA,GAAW,OAAO;CAC7E,IAAI,OAAO,YAAY,OAAO,WAAW,GACvC,MAAM,IAAID,eAAAA,YACRC,eAAAA,gBAAgB,YAChB,qDACF;CAEF,MAAM,SAAS,CAAC,GAAG,OAAO,YAAY,MAAM,CAAC,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC;CAClE,OAAO,OAAO,MAAM,MAAM,KAAK,KAAK,KAAK,OAAO,OAAO,SAAS;AAClE;;;;;;;AAQA,SAAgB,uBACd,UACoB;CACpB,IAAI,aAAa,KAAA,GAAW,OAAO;CACnC,OAAO,SAAS,SAAS,UAAW,SAAS,SAAS,IAAK,KAAA;AAC7D;;;;;;;;;;;AAYA,SAAgB,cAAc,QAA4B,OAAuB;CAC/E,IAAI,OAAO,SAAS,gBAAgB,OAAO,UAAU,KAAA,GAAW,OAAO;CACvE,IAAI,OAAO,MAAM,OAAO,WAAW,GACjC,MAAM,IAAID,eAAAA,YACRC,eAAAA,gBAAgB,YAChB,+CACF;CAEF,MAAM,SAAS,CAAC,GAAG,OAAO,MAAM,MAAM,CAAC,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC;CAC5D,OAAO,OAAO,MAAM,MAAM,KAAK,KAAK,KAAK,OAAO,OAAO,SAAS;AAClE"}
@@ -0,0 +1,85 @@
1
+ import { h as EngineError, y as EngineErrorCode } from "./format-Dgg428Kb.js";
2
+ import { i as hasLocalEngineBrand } from "./LocalDocumentHandle-DAPdaOt_.js";
3
+ //#region src/engine/LocalEngine.ts
4
+ /** Whether `engine` is the local engine, with its fonts and `warmup()`. */
5
+ function isLocalEngine(engine) {
6
+ return hasLocalEngineBrand(engine);
7
+ }
8
+ //#endregion
9
+ //#region src/engine/DocumentRenderService.ts
10
+ const CONTINUOUS_RENDER_POLICY = { kind: "continuous" };
11
+ /**
12
+ * Conform a full-page viewport to a render policy — the one snap
13
+ * implementation, shared by every engine and plugin. Pure and explicit
14
+ * by design:
15
+ *
16
+ * - `continuous` → identity (local/cloud plugin code stays byte-identical).
17
+ * - `lattice` → returns a `width`-kind viewport at the smallest ladder
18
+ * width ≥ the requested detail (snap up: always crisp, CSS downscales
19
+ * for free), capped at the largest width — detail beyond the cap is the
20
+ * tile pyramid's job, by design.
21
+ * - `scale`-kind requests convert through the page's width in PDF user
22
+ * units — pass `opts.pageWidth` (the caller has it from the layout);
23
+ * omitting it for a scale viewport under a lattice policy is a
24
+ * programmer error and throws `InvalidArg`.
25
+ */
26
+ function snapFullPageViewport(policy, viewport, opts) {
27
+ if (policy.kind === "continuous") return viewport;
28
+ if (policy.fullPage.widths.length === 0) throw new EngineError(EngineErrorCode.InvalidArg, "render policy has an empty width ladder");
29
+ const widths = [...policy.fullPage.widths].sort((a, b) => a - b);
30
+ let requested;
31
+ if (viewport.kind === "width") requested = viewport.width;
32
+ else {
33
+ const pageWidth = opts?.pageWidth;
34
+ if (pageWidth === void 0 || pageWidth <= 0) throw new EngineError(EngineErrorCode.InvalidArg, "snapping a scale viewport to a width lattice requires opts.pageWidth");
35
+ requested = (viewport.scale ?? 1) * pageWidth;
36
+ }
37
+ return {
38
+ kind: "width",
39
+ width: widths.find((width) => width >= requested) ?? widths[widths.length - 1]
40
+ };
41
+ }
42
+ /**
43
+ * Conform an annotation-appearance scale to the policy's appearance
44
+ * lattice. Same discipline as {@link snapFullPageViewport}: identity on
45
+ * continuous (and when the policy carries no appearance block), snap up,
46
+ * cap at the largest point. Callers derive `scale` from the page's
47
+ * effective render scale (`snappedWidth / pageWidth`, × devicePixelRatio
48
+ * as needed) so composites stay crisp against the page raster.
49
+ */
50
+ function snapAppearanceScale(policy, scale) {
51
+ if (policy.kind === "continuous" || policy.appearances === void 0) return scale;
52
+ if (policy.appearances.scales.length === 0) throw new EngineError(EngineErrorCode.InvalidArg, "render policy has an empty appearance-scale lattice");
53
+ const scales = [...policy.appearances.scales].sort((a, b) => a - b);
54
+ return scales.find((s) => s >= scale) ?? scales[scales.length - 1];
55
+ }
56
+ /**
57
+ * The scale an appearance render's viewport puts on the appearance lattice:
58
+ * a `scale` viewport's scale (1 when omitted), and `undefined` for a
59
+ * `width` viewport, whose scale depends on the page's size and so is never
60
+ * on the lattice.
61
+ */
62
+ function appearanceLatticeScale(viewport) {
63
+ if (viewport === void 0) return 1;
64
+ return viewport.kind === "scale" ? viewport.scale ?? 1 : void 0;
65
+ }
66
+ /**
67
+ * Conform a tile-pyramid scale to the policy's tile lattice — the third
68
+ * member of the `snap<PolicyBlock><Quantity>` family. Identity on
69
+ * continuous and while the deployment doesn't advertise a `tiles` block
70
+ * (the block is reserved until the deep-zoom vertical ships server-side;
71
+ * the tiling client uses its own default pyramid then — see
72
+ * plugin-render). Snap up, cap at the largest scale: per-tile cost is
73
+ * constant by construction (`tileSize²` pixels regardless of level), so
74
+ * the cap bounds artifact count, not memory.
75
+ */
76
+ function snapTileScale(policy, scale) {
77
+ if (policy.kind === "continuous" || policy.tiles === void 0) return scale;
78
+ if (policy.tiles.scales.length === 0) throw new EngineError(EngineErrorCode.InvalidArg, "render policy has an empty tile-scale lattice");
79
+ const scales = [...policy.tiles.scales].sort((a, b) => a - b);
80
+ return scales.find((s) => s >= scale) ?? scales[scales.length - 1];
81
+ }
82
+ //#endregion
83
+ export { snapTileScale as a, snapFullPageViewport as i, appearanceLatticeScale as n, isLocalEngine as o, snapAppearanceScale as r, CONTINUOUS_RENDER_POLICY as t };
84
+
85
+ //# sourceMappingURL=DocumentRenderService-DV3J9lMz.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DocumentRenderService-DV3J9lMz.js","names":[],"sources":["../src/engine/LocalEngine.ts","../src/engine/DocumentRenderService.ts"],"sourcesContent":["import type { Engine } from './Engine';\nimport type { FontService } from './FontService';\nimport type { LocalDocumentHandle } from './LocalDocumentHandle';\nimport { hasLocalEngineBrand } from './localEngineBrand';\nimport type { OpenInput, OpenOptions } from '../dto/OpenInput';\nimport { AbortablePromise } from '../promise/AbortablePromise';\n\n/**\n * The engine that runs PDFium itself, in the browser or in Node: the shared\n * {@link Engine} and what only it can do. `localEngine()` returns one, so an\n * app built on it reaches these without a check; code that takes any engine\n * checks with {@link isLocalEngine}.\n */\nexport interface LocalEngine extends Engine {\n open(input: OpenInput, options?: OpenOptions): AbortablePromise<LocalDocumentHandle>;\n\n /**\n * Start booting the engine (Worker spawn, WASM compile) without doing any\n * work. Idempotent and non-blocking: the engine boots on first use anyway,\n * so this only overlaps that boot with the app's own start.\n */\n warmup(): void;\n\n /** Runtime font registration and fallback fonts. See {@link FontService}. */\n readonly fonts: FontService;\n}\n\n/** Whether `engine` is the local engine, with its fonts and `warmup()`. */\nexport function isLocalEngine(engine: Engine): engine is LocalEngine {\n return hasLocalEngineBrand(engine);\n}\n","import { EngineError } from '../errors/EngineError';\nimport { EngineErrorCode } from '../errors/EngineErrorCode';\nimport type { PageRenderViewport } from '../dto/PageRender';\nimport type { AbortablePromise } from '../promise/AbortablePromise';\n\n/**\n * The engine's render-parameter policy.\n *\n * - `continuous` — any viewport renders exactly as requested. The local\n * engine always answers this: rendering is in-process, there is no\n * shared cache to protect, and exactness is the local product promise.\n * - `lattice` — the deployment treats a finite set of render points as\n * durable, CDN-shared artifacts. The bounded quantity\n * is output pixels, never zoom:\n *\n * - `fullPage.widths` — full-page renders quantize on `viewport.width`\n * (a scale lattice bounds artifact count but not size: PDF page space\n * is effectively unbounded, so scale 1 of a poster page is a memory\n * bomb while width caps the dominant dimension by construction).\n * - `tiles` — reserved for the deep-zoom vertical: a scale-based\n * pyramid × fixed tile size, where per-job cost is constant. Absent\n * until the tiling plugin ships; reserving the shape keeps the SDK\n * contract from churning twice.\n * - `maxRenderPixels` — the worker-side output budget for degenerate\n * geometry (width bounds width, not height).\n *\n * The SDK never conforms a request implicitly — the same `render.image`\n * call must not return different pixels on local vs cloud. Conformance is\n * the caller's visible choice via {@link snapFullPageViewport}.\n */\nexport type EngineRenderPolicy =\n | { readonly kind: 'continuous' }\n | {\n readonly kind: 'lattice';\n readonly fullPage: { readonly widths: readonly number[] };\n readonly tiles?: {\n readonly tileSizes: readonly number[];\n readonly scales: readonly number[];\n };\n /**\n * Annotation-appearance lattice — scale-based, unlike full pages:\n * an appearance is sized by `annotation.rect × scale`, rects span\n * orders of magnitude (a 4pt caret vs a page-sized stamp), and the\n * composite must track the page's effective render scale or\n * annotations sit blurry on a crisp raster. Small images → the\n * ladder affords finer, taller steps than pages ever could.\n */\n readonly appearances?: { readonly scales: readonly number[] };\n readonly maxRenderPixels?: number;\n readonly formats: readonly ('webp' | 'png')[];\n readonly background: 'white';\n readonly enforced: boolean;\n };\n\nexport const CONTINUOUS_RENDER_POLICY: EngineRenderPolicy = { kind: 'continuous' };\n\n/**\n * Document-scoped render policy surface (`doc.render`). Async because the\n * cloud engine learns its policy from `/v1/access`; the local engine\n * resolves immediately with `continuous`.\n *\n * Per-page rendering itself stays on `page(pon).render` — this service\n * carries policy, not pixels.\n */\nexport interface DocumentRenderService {\n getPolicy(): AbortablePromise<EngineRenderPolicy>;\n}\n\n/**\n * Conform a full-page viewport to a render policy — the one snap\n * implementation, shared by every engine and plugin. Pure and explicit\n * by design:\n *\n * - `continuous` → identity (local/cloud plugin code stays byte-identical).\n * - `lattice` → returns a `width`-kind viewport at the smallest ladder\n * width ≥ the requested detail (snap up: always crisp, CSS downscales\n * for free), capped at the largest width — detail beyond the cap is the\n * tile pyramid's job, by design.\n * - `scale`-kind requests convert through the page's width in PDF user\n * units — pass `opts.pageWidth` (the caller has it from the layout);\n * omitting it for a scale viewport under a lattice policy is a\n * programmer error and throws `InvalidArg`.\n */\nexport function snapFullPageViewport(\n policy: EngineRenderPolicy,\n viewport: PageRenderViewport,\n opts?: { pageWidth?: number },\n): PageRenderViewport {\n if (policy.kind === 'continuous') return viewport;\n if (policy.fullPage.widths.length === 0) {\n throw new EngineError(EngineErrorCode.InvalidArg, 'render policy has an empty width ladder');\n }\n const widths = [...policy.fullPage.widths].sort((a, b) => a - b);\n\n let requested: number;\n if (viewport.kind === 'width') {\n requested = viewport.width;\n } else {\n const pageWidth = opts?.pageWidth;\n if (pageWidth === undefined || pageWidth <= 0) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n 'snapping a scale viewport to a width lattice requires opts.pageWidth',\n );\n }\n requested = (viewport.scale ?? 1) * pageWidth;\n }\n\n const snapped = widths.find((width) => width >= requested) ?? widths[widths.length - 1]!;\n return { kind: 'width', width: snapped };\n}\n\n/**\n * Conform an annotation-appearance scale to the policy's appearance\n * lattice. Same discipline as {@link snapFullPageViewport}: identity on\n * continuous (and when the policy carries no appearance block), snap up,\n * cap at the largest point. Callers derive `scale` from the page's\n * effective render scale (`snappedWidth / pageWidth`, × devicePixelRatio\n * as needed) so composites stay crisp against the page raster.\n */\nexport function snapAppearanceScale(policy: EngineRenderPolicy, scale: number): number {\n if (policy.kind === 'continuous' || policy.appearances === undefined) return scale;\n if (policy.appearances.scales.length === 0) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n 'render policy has an empty appearance-scale lattice',\n );\n }\n const scales = [...policy.appearances.scales].sort((a, b) => a - b);\n return scales.find((s) => s >= scale) ?? scales[scales.length - 1]!;\n}\n\n/**\n * The scale an appearance render's viewport puts on the appearance lattice:\n * a `scale` viewport's scale (1 when omitted), and `undefined` for a\n * `width` viewport, whose scale depends on the page's size and so is never\n * on the lattice.\n */\nexport function appearanceLatticeScale(\n viewport: PageRenderViewport | undefined,\n): number | undefined {\n if (viewport === undefined) return 1;\n return viewport.kind === 'scale' ? (viewport.scale ?? 1) : undefined;\n}\n\n/**\n * Conform a tile-pyramid scale to the policy's tile lattice — the third\n * member of the `snap<PolicyBlock><Quantity>` family. Identity on\n * continuous and while the deployment doesn't advertise a `tiles` block\n * (the block is reserved until the deep-zoom vertical ships server-side;\n * the tiling client uses its own default pyramid then — see\n * plugin-render). Snap up, cap at the largest scale: per-tile cost is\n * constant by construction (`tileSize²` pixels regardless of level), so\n * the cap bounds artifact count, not memory.\n */\nexport function snapTileScale(policy: EngineRenderPolicy, scale: number): number {\n if (policy.kind === 'continuous' || policy.tiles === undefined) return scale;\n if (policy.tiles.scales.length === 0) {\n throw new EngineError(\n EngineErrorCode.InvalidArg,\n 'render policy has an empty tile-scale lattice',\n );\n }\n const scales = [...policy.tiles.scales].sort((a, b) => a - b);\n return scales.find((s) => s >= scale) ?? scales[scales.length - 1]!;\n}\n"],"mappings":";;;;AA4BA,SAAgB,cAAc,QAAuC;CACnE,OAAO,oBAAoB,MAAM;AACnC;;;ACwBA,MAAa,2BAA+C,EAAE,MAAM,aAAa;;;;;;;;;;;;;;;;AA6BjF,SAAgB,qBACd,QACA,UACA,MACoB;CACpB,IAAI,OAAO,SAAS,cAAc,OAAO;CACzC,IAAI,OAAO,SAAS,OAAO,WAAW,GACpC,MAAM,IAAI,YAAY,gBAAgB,YAAY,yCAAyC;CAE7F,MAAM,SAAS,CAAC,GAAG,OAAO,SAAS,MAAM,CAAC,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC;CAE/D,IAAI;CACJ,IAAI,SAAS,SAAS,SACpB,YAAY,SAAS;MAChB;EACL,MAAM,YAAY,MAAM;EACxB,IAAI,cAAc,KAAA,KAAa,aAAa,GAC1C,MAAM,IAAI,YACR,gBAAgB,YAChB,sEACF;EAEF,aAAa,SAAS,SAAS,KAAK;CACtC;CAGA,OAAO;EAAE,MAAM;EAAS,OADR,OAAO,MAAM,UAAU,SAAS,SAAS,KAAK,OAAO,OAAO,SAAS;CAC9C;AACzC;;;;;;;;;AAUA,SAAgB,oBAAoB,QAA4B,OAAuB;CACrF,IAAI,OAAO,SAAS,gBAAgB,OAAO,gBAAgB,KAAA,GAAW,OAAO;CAC7E,IAAI,OAAO,YAAY,OAAO,WAAW,GACvC,MAAM,IAAI,YACR,gBAAgB,YAChB,qDACF;CAEF,MAAM,SAAS,CAAC,GAAG,OAAO,YAAY,MAAM,CAAC,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC;CAClE,OAAO,OAAO,MAAM,MAAM,KAAK,KAAK,KAAK,OAAO,OAAO,SAAS;AAClE;;;;;;;AAQA,SAAgB,uBACd,UACoB;CACpB,IAAI,aAAa,KAAA,GAAW,OAAO;CACnC,OAAO,SAAS,SAAS,UAAW,SAAS,SAAS,IAAK,KAAA;AAC7D;;;;;;;;;;;AAYA,SAAgB,cAAc,QAA4B,OAAuB;CAC/E,IAAI,OAAO,SAAS,gBAAgB,OAAO,UAAU,KAAA,GAAW,OAAO;CACvE,IAAI,OAAO,MAAM,OAAO,WAAW,GACjC,MAAM,IAAI,YACR,gBAAgB,YAChB,+CACF;CAEF,MAAM,SAAS,CAAC,GAAG,OAAO,MAAM,MAAM,CAAC,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC;CAC5D,OAAO,OAAO,MAAM,MAAM,KAAK,KAAK,KAAK,OAAO,OAAO,SAAS;AAClE"}