nuvra 0.2.0 → 0.3.0

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.
@@ -75,7 +75,26 @@ var e = {
75
75
  size: "a4",
76
76
  orientation: "portrait",
77
77
  margins: { ...t[0].margins }
78
- }), s = ({ size: t, orientation: r, margins: i }) => {
78
+ }), s = () => ({
79
+ left: "",
80
+ center: "",
81
+ right: ""
82
+ }), c = (e) => !!(e && (e.left || e.center || e.right)), l = [
83
+ "page",
84
+ "pages",
85
+ "date",
86
+ "title"
87
+ ], u = RegExp(`\\{(${l.join("|")})\\}`, "g"), d = () => {
88
+ let e = /* @__PURE__ */ new Date(), t = (e) => String(e).padStart(2, "0");
89
+ return `${t(e.getDate())}.${t(e.getMonth() + 1)}.${e.getFullYear()}`;
90
+ }, f = (e, t) => e.replace(u, (e, n) => n === "page" ? String(t.page) : n === "pages" ? String(t.pages) : n === "title" ? t.title : d()), p = () => ({
91
+ text: "",
92
+ color: "#9ca3af",
93
+ diagonal: !0
94
+ }), m = (e) => !!e?.text.trim(), h = .86, g = .62, _ = 24, v = .4, y = (e, t, n, r) => {
95
+ let i = r ? Math.sqrt(e * e + t * t) : e, a = Math.max(4, n.trim().length) * g, o = i * h / a;
96
+ return Math.round(Math.max(_, Math.min(o, t * v)));
97
+ }, b = ({ size: t, orientation: r, margins: i }) => {
79
98
  let o = e[t] ?? e.a4, s = r === "portrait";
80
99
  return {
81
100
  width: a(s ? o.width : o.height),
@@ -86,8 +105,8 @@ var e = {
86
105
  marginBottom: a(i.bottom),
87
106
  marginLeft: a(i.left)
88
107
  };
89
- }, c = (e, t) => Object.keys(e).every((n) => Math.abs(e[n] - t[n]) < i);
108
+ }, x = (e, t) => Object.keys(e).every((n) => Math.abs(e[n] - t[n]) < i);
90
109
  //#endregion
91
- export { c as a, s as i, e as n, o as r, t };
110
+ export { o as a, c, f as d, y as f, s as i, m as l, t as n, p as o, e as r, b as s, l as t, x as u };
92
111
 
93
- //# sourceMappingURL=page-CEEleKNI.js.map
112
+ //# sourceMappingURL=page-DL7Oj2o8.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-DL7Oj2o8.js","names":[],"sources":["../src/core/page.ts"],"sourcesContent":["/** Supported paper formats. */\nexport type PageSizeKey = 'a3' | 'a4' | 'a5' | 'letter' | 'legal';\n/** Paper orientation. */\nexport type PageOrientation = 'portrait' | 'landscape';\n/** `page` shows sheets like a word processor, `web` a continuous surface. */\nexport type DocumentViewMode = 'page' | 'web';\n\n/** Page margins in millimetres. */\nexport interface PageMargins {\n /** Top margin. */\n top: number;\n /** Right margin. */\n right: number;\n /** Bottom margin. */\n bottom: number;\n /** Left margin. */\n left: number;\n}\n\n/** Text repeated in the top or bottom margin of every page, in three aligned parts as in office suites. */\nexport interface PageHeaderFooter {\n /** Left-aligned part. */\n left: string;\n /** Centred part. */\n center: string;\n /** Right-aligned part. */\n right: string;\n}\n\n/** Text drawn behind the content of every page, such as “DRAFT” or “COPY”. */\nexport interface PageWatermark {\n /** Text of the watermark; without it the page has none. */\n text: string;\n /** Colour of the text; it is drawn faintly, so a mid grey suits most documents. */\n color: string;\n /** Whether the text runs diagonally across the page instead of straight across it. */\n diagonal: boolean;\n}\n\n/** Page setup chosen by the user; the host can persist it with `v-model:page`. */\nexport interface PageSettings {\n /** Paper format. */\n size: PageSizeKey;\n /** Paper orientation. */\n orientation: PageOrientation;\n /** Margins in millimetres. */\n margins: PageMargins;\n /** Text repeated in the top margin of every page; omitted while the document has no header. */\n header?: PageHeaderFooter;\n /** Text repeated in the bottom margin of every page; omitted while the document has no footer. */\n footer?: PageHeaderFooter;\n /** Watermark drawn behind the text of every page; omitted while the document has none. */\n watermark?: PageWatermark;\n}\n\n/** Page geometry in CSS pixels, ready for layout. */\nexport interface PageMetrics {\n /** Sheet width. */\n width: number;\n /** Sheet height. */\n height: number;\n /** Grey space between two sheets. */\n gap: number;\n /** Top margin. */\n marginTop: number;\n /** Right margin. */\n marginRight: number;\n /** Bottom margin. */\n marginBottom: number;\n /** Left margin. */\n marginLeft: number;\n}\n\n/** Portrait dimensions of a paper format in millimetres. */\ninterface PaperSize {\n /** Name shown in the page setup. */\n label: string;\n /** Portrait width. */\n width: number;\n /** Portrait height. */\n height: number;\n}\n\n/** Paper sizes in millimetres (portrait). */\nexport const PAGE_SIZES: Record<PageSizeKey, PaperSize> = {\n a3: { label: 'A3', width: 297, height: 420 },\n a4: { label: 'A4', width: 210, height: 297 },\n a5: { label: 'A5', width: 148, height: 210 },\n letter: { label: 'Letter', width: 215.9, height: 279.4 },\n legal: { label: 'Legal', width: 215.9, height: 355.6 }\n};\n\n/** Margin presets offered by the page setup, in millimetres; the key doubles as the label suffix. */\nexport const MARGIN_PRESETS = [\n { key: 'normal', margins: { top: 25.4, right: 25.4, bottom: 25.4, left: 25.4 } },\n { key: 'narrow', margins: { top: 12.7, right: 12.7, bottom: 12.7, left: 12.7 } },\n { key: 'moderate', margins: { top: 25.4, right: 19.1, bottom: 25.4, left: 19.1 } },\n { key: 'wide', margins: { top: 25.4, right: 50.8, bottom: 25.4, left: 50.8 } },\n /** O‘zDSt 1.14 requisites for official documents. */\n { key: 'official', margins: { top: 20, right: 15, bottom: 20, left: 30 } }\n] as const satisfies ReadonlyArray<{ key: string; margins: PageMargins }>;\n\n/** Smallest zoom in percent; low enough for an A4 sheet to fit a phone screen. */\nexport const ZOOM_MIN = 30;\n/** Largest zoom in percent. */\nexport const ZOOM_MAX = 200;\n/** Zoom change per step of the zoom buttons and slider, in percent. */\nexport const ZOOM_STEP = 10;\n\n/** Grey space between two sheets in page view, in CSS pixels. */\nconst PAGE_GAP = 20;\n/** CSS pixels per millimetre at 96 DPI. */\nconst PX_PER_MM = 96 / 25.4;\n/** Margin differences below this many millimetres count as equal (rounding of unit conversions). */\nconst MARGIN_TOLERANCE_MM = 0.05;\n\n/** Converts millimetres to CSS pixels. */\nconst mmToPx = (value: number): number => value * PX_PER_MM;\n\n/** Default page setup: portrait A4 with normal margins. */\nexport const createPageSettings = (): PageSettings => ({\n size: 'a4',\n orientation: 'portrait',\n margins: { ...MARGIN_PRESETS[0].margins }\n});\n\n/** An empty header or footer, used when the user opens the form for the first time. */\nexport const createHeaderFooter = (): PageHeaderFooter => ({ left: '', center: '', right: '' });\n\n/** Whether a header or footer holds any text at all. */\nexport const hasHeaderFooterText = (value: PageHeaderFooter | undefined): boolean =>\n Boolean(value && (value.left || value.center || value.right));\n\n/** Tokens a header or footer text may contain, replaced when the text is drawn on a page. */\nexport const HEADER_FOOTER_TOKENS = ['page', 'pages', 'date', 'title'] as const;\n\n/** One of the tokens a header or footer text may contain. */\nexport type HeaderFooterToken = (typeof HEADER_FOOTER_TOKENS)[number];\n\n/** Values the tokens of a header or footer are replaced with. */\nexport interface HeaderFooterContext {\n /** Number of the page the text is drawn on. */\n page: number;\n /** Number of pages in the document. */\n pages: number;\n /** Document title. */\n title: string;\n}\n\n/** Pattern of the tokens, built from their names so both stay in step. */\nconst TOKEN_PATTERN = new RegExp(`\\\\{(${HEADER_FOOTER_TOKENS.join('|')})\\\\}`, 'g');\n\n/** Today's date as `dd.mm.yyyy`, the format used in Uzbek documents. */\nconst today = (): string => {\n const now = new Date();\n const twoDigits = (value: number) => String(value).padStart(2, '0');\n return `${twoDigits(now.getDate())}.${twoDigits(now.getMonth() + 1)}.${now.getFullYear()}`;\n};\n\n/** Replaces the `{page}`, `{pages}`, `{date}` and `{title}` tokens of a header or footer text. */\nexport const renderHeaderFooter = (text: string, context: HeaderFooterContext): string =>\n text.replace(TOKEN_PATTERN, (_, token: string) => {\n if (token === 'page') return String(context.page);\n if (token === 'pages') return String(context.pages);\n if (token === 'title') return context.title;\n return today();\n });\n\n/** An empty watermark in the default colour, used when the user opens the form for the first time. */\nexport const createWatermark = (): PageWatermark => ({ text: '', color: '#9ca3af', diagonal: true });\n\n/** Whether a watermark has any text to draw. */\nexport const hasWatermarkText = (value: PageWatermark | undefined): boolean => Boolean(value?.text.trim());\n\n/** How much of the paper the watermark text spans. */\nconst WATERMARK_FILL = 0.86;\n/** Average width of a character relative to the font size, used to fit the text onto the paper. */\nconst AVERAGE_CHARACTER_WIDTH = 0.62;\n/** Smallest watermark font size in pixels, so a short text is still large. */\nconst MIN_WATERMARK_SIZE = 24;\n/** Largest watermark font size, as a share of the paper height. */\nconst MAX_WATERMARK_HEIGHT_SHARE = 0.4;\n/** Angle the diagonal watermark is rotated by, in degrees. */\nexport const WATERMARK_ANGLE = -35;\n\n/** Font size in pixels at which a watermark text spans the paper, straight across it or diagonally. */\nexport const watermarkFontSize = (width: number, height: number, text: string, diagonal: boolean): number => {\n const span = diagonal ? Math.sqrt(width * width + height * height) : width;\n const characters = Math.max(4, text.trim().length) * AVERAGE_CHARACTER_WIDTH;\n const size = (span * WATERMARK_FILL) / characters;\n return Math.round(Math.max(MIN_WATERMARK_SIZE, Math.min(size, height * MAX_WATERMARK_HEIGHT_SHARE)));\n};\n\n/** Converts page settings into pixel geometry; an unknown paper size falls back to A4. */\nexport const getPageMetrics = ({ size, orientation, margins }: PageSettings): PageMetrics => {\n const paper = PAGE_SIZES[size] ?? PAGE_SIZES.a4;\n const portrait = orientation === 'portrait';\n return {\n width: mmToPx(portrait ? paper.width : paper.height),\n height: mmToPx(portrait ? paper.height : paper.width),\n gap: PAGE_GAP,\n marginTop: mmToPx(margins.top),\n marginRight: mmToPx(margins.right),\n marginBottom: mmToPx(margins.bottom),\n marginLeft: mmToPx(margins.left)\n };\n};\n\n/** Whether two margin sets are equal, used to highlight the matching preset. */\nexport const isSameMargins = (a: PageMargins, b: PageMargins): boolean =>\n (Object.keys(a) as Array<keyof PageMargins>).every(side => Math.abs(a[side] - b[side]) < MARGIN_TOLERANCE_MM);\n"],"mappings":";AAoFA,IAAa,IAA6C;CACxD,IAAI;EAAE,OAAO;EAAM,OAAO;EAAK,QAAQ;CAAI;CAC3C,IAAI;EAAE,OAAO;EAAM,OAAO;EAAK,QAAQ;CAAI;CAC3C,IAAI;EAAE,OAAO;EAAM,OAAO;EAAK,QAAQ;CAAI;CAC3C,QAAQ;EAAE,OAAO;EAAU,OAAO;EAAO,QAAQ;CAAM;CACvD,OAAO;EAAE,OAAO;EAAS,OAAO;EAAO,QAAQ;CAAM;AACvD,GAGa,IAAiB;CAC5B;EAAE,KAAK;EAAU,SAAS;GAAE,KAAK;GAAM,OAAO;GAAM,QAAQ;GAAM,MAAM;EAAK;CAAE;CAC/E;EAAE,KAAK;EAAU,SAAS;GAAE,KAAK;GAAM,OAAO;GAAM,QAAQ;GAAM,MAAM;EAAK;CAAE;CAC/E;EAAE,KAAK;EAAY,SAAS;GAAE,KAAK;GAAM,OAAO;GAAM,QAAQ;GAAM,MAAM;EAAK;CAAE;CACjF;EAAE,KAAK;EAAQ,SAAS;GAAE,KAAK;GAAM,OAAO;GAAM,QAAQ;GAAM,MAAM;EAAK;CAAE;CAE7E;EAAE,KAAK;EAAY,SAAS;GAAE,KAAK;GAAI,OAAO;GAAI,QAAQ;GAAI,MAAM;EAAG;CAAE;AAC3E,GAUM,IAAW,IAEX,IAAY,KAAK,MAEjB,IAAsB,KAGtB,KAAU,MAA0B,IAAQ,GAGrC,WAA0C;CACrD,MAAM;CACN,aAAa;CACb,SAAS,EAAE,GAAG,EAAe,EAAE,CAAC,QAAQ;AAC1C,IAGa,WAA8C;CAAE,MAAM;CAAI,QAAQ;CAAI,OAAO;AAAG,IAGhF,KAAuB,MAClC,GAAQ,MAAU,EAAM,QAAQ,EAAM,UAAU,EAAM,SAG3C,IAAuB;CAAC;CAAQ;CAAS;CAAQ;AAAO,GAgB/D,IAAoB,OAAO,OAAO,EAAqB,KAAK,GAAG,EAAE,OAAO,GAAG,GAG3E,UAAsB;CAC1B,IAAM,oBAAM,IAAI,KAAK,GACf,KAAa,MAAkB,OAAO,CAAK,CAAC,CAAC,SAAS,GAAG,GAAG;CAClE,OAAO,GAAG,EAAU,EAAI,QAAQ,CAAC,EAAE,GAAG,EAAU,EAAI,SAAS,IAAI,CAAC,EAAE,GAAG,EAAI,YAAY;AACzF,GAGa,KAAsB,GAAc,MAC/C,EAAK,QAAQ,IAAgB,GAAG,MAC1B,MAAU,SAAe,OAAO,EAAQ,IAAI,IAC5C,MAAU,UAAgB,OAAO,EAAQ,KAAK,IAC9C,MAAU,UAAgB,EAAQ,QAC/B,EAAM,CACd,GAGU,WAAwC;CAAE,MAAM;CAAI,OAAO;CAAW,UAAU;AAAK,IAGrF,KAAoB,MAA8C,EAAQ,GAAO,KAAK,KAAK,GAGlG,IAAiB,KAEjB,IAA0B,KAE1B,IAAqB,IAErB,IAA6B,IAKtB,KAAqB,GAAe,GAAgB,GAAc,MAA8B;CAC3G,IAAM,IAAO,IAAW,KAAK,KAAK,IAAQ,IAAQ,IAAS,CAAM,IAAI,GAC/D,IAAa,KAAK,IAAI,GAAG,EAAK,KAAK,CAAC,CAAC,MAAM,IAAI,GAC/C,IAAQ,IAAO,IAAkB;CACvC,OAAO,KAAK,MAAM,KAAK,IAAI,GAAoB,KAAK,IAAI,GAAM,IAAS,CAA0B,CAAC,CAAC;AACrG,GAGa,KAAkB,EAAE,SAAM,gBAAa,iBAAyC;CAC3F,IAAM,IAAQ,EAAW,MAAS,EAAW,IACvC,IAAW,MAAgB;CACjC,OAAO;EACL,OAAO,EAAO,IAAW,EAAM,QAAQ,EAAM,MAAM;EACnD,QAAQ,EAAO,IAAW,EAAM,SAAS,EAAM,KAAK;EACpD,KAAK;EACL,WAAW,EAAO,EAAQ,GAAG;EAC7B,aAAa,EAAO,EAAQ,KAAK;EACjC,cAAc,EAAO,EAAQ,MAAM;EACnC,YAAY,EAAO,EAAQ,IAAI;CACjC;AACF,GAGa,KAAiB,GAAgB,MAC3C,OAAO,KAAK,CAAC,CAAC,CAA8B,OAAM,MAAQ,KAAK,IAAI,EAAE,KAAQ,EAAE,EAAK,IAAI,CAAmB"}
package/dist/style.css CHANGED
@@ -1,2 +1,2 @@
1
- .doc-icon[data-v-4e391eda]{flex:none}.doc-bubble[data-v-41a7aa00]{z-index:2100;box-sizing:border-box;border:1px solid var(--nuvra-border-light);color:var(--nuvra-text);background:var(--nuvra-bg-overlay);border-radius:8px;align-items:center;gap:1px;margin:0;padding:3px;display:flex;position:fixed;inset:auto;overflow:visible;box-shadow:0 6px 20px #10182829}.doc-bubble.is-hidden[data-v-41a7aa00]{visibility:hidden}.doc-bubble__divider[data-v-41a7aa00]{background:var(--nuvra-border-lighter);flex:0 0 1px;align-self:stretch;margin:3px 4px}.doc-bubble .doc-tb-button.is-danger[data-v-41a7aa00]:hover:not(:disabled){color:var(--nuvra-color-danger);background:var(--nuvra-color-danger-soft)}.doc-bubble__link[data-v-41a7aa00]{max-width:260px;color:var(--nuvra-color-primary);align-items:center;gap:5px;padding:0 6px;font-size:12px;text-decoration:none;display:inline-flex}.doc-bubble__link span[data-v-41a7aa00]{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.doc-bubble__form[data-v-41a7aa00]{gap:4px;width:280px;display:flex}.object-overlay[data-v-7da0d742]{z-index:3;pointer-events:none;position:absolute;inset:0}.object-overlay__image[data-v-7da0d742]{box-sizing:border-box;outline-offset:1px;outline:2px solid #3b82f6;position:absolute}.object-overlay__handle[data-v-7da0d742]{box-sizing:border-box;pointer-events:auto;background:#fff;border:1.5px solid #3b82f6;border-radius:2px;width:10px;height:10px;position:absolute}.object-overlay__handle.is-top-left[data-v-7da0d742]{cursor:nwse-resize;top:-6px;left:-6px}.object-overlay__handle.is-top-right[data-v-7da0d742]{cursor:nesw-resize;top:-6px;right:-6px}.object-overlay__handle.is-bottom-left[data-v-7da0d742]{cursor:nesw-resize;bottom:-6px;left:-6px}.object-overlay__handle.is-bottom-right[data-v-7da0d742]{cursor:nwse-resize;bottom:-6px;right:-6px}.object-overlay__size[data-v-7da0d742]{color:#fff;background:#101828bf;border-radius:4px;padding:2px 6px;font:11px/16px system-ui,sans-serif;position:absolute;bottom:4px;right:4px}.object-overlay__guide[data-v-7da0d742]{border-left:1px dashed #3b82f6;width:0;position:absolute}.doc-canvas[data-v-10cbe4d1]{box-sizing:border-box;min-height:0;padding:var(--doc-editor-canvas-padding);overscroll-behavior:contain;background:#e9ebef;flex:auto;position:relative;overflow:auto}.doc-canvas.is-auto[data-v-10cbe4d1]{min-height:var(--doc-editor-min-height);max-height:var(--doc-editor-max-height);flex:none}.doc-canvas__sizer[data-v-10cbe4d1]{margin:0 auto;position:relative}.doc-canvas__stage[data-v-10cbe4d1]{--page-height:1123px;--pages-height:1123px;--margin-top:96px;--margin-right:96px;--margin-bottom:96px;--margin-left:96px;--page-break-label:"";transform-origin:0 0;position:absolute;top:0;left:0}.doc-canvas.is-web .doc-canvas__stage[data-v-10cbe4d1]{background:#fff;box-shadow:0 0 0 1px #1018280f,0 1px 4px #10182814}.doc-canvas__sheets[data-v-10cbe4d1]{pointer-events:none;position:absolute;inset:0}.doc-canvas__sheet[data-v-10cbe4d1]{width:100%;height:var(--page-height);background:#fff;position:absolute;left:0;box-shadow:0 0 0 1px #1018280f,0 2px 8px #1018281a}.doc-canvas__page-number[data-v-10cbe4d1]{right:0;bottom:calc(var(--margin-bottom) / 2 - 8px);color:#98a2b3;text-align:center;font:11px/16px system-ui,sans-serif;position:absolute;left:0}.doc-canvas__content[data-v-10cbe4d1]{box-sizing:border-box;min-height:inherit;caret-color:#1f2328;outline:none;position:relative}.doc-canvas.is-page .doc-canvas__content[data-v-10cbe4d1]{min-height:var(--pages-height);padding:var(--margin-top) var(--margin-right) var(--margin-bottom) var(--margin-left)}.doc-canvas.is-web .doc-canvas__content[data-v-10cbe4d1]{padding:40px 56px}.doc-canvas.is-auto.is-web .doc-canvas__content[data-v-10cbe4d1]{padding:16px 20px}.find-bar[data-v-120d7f24]{z-index:5;border:1px solid var(--nuvra-border-light);background:var(--nuvra-bg-overlay);box-shadow:var(--nuvra-shadow);border-radius:10px;align-items:flex-start;gap:2px;padding:5px;display:flex;position:absolute;top:8px;right:20px}.find-bar__rows[data-v-120d7f24]{gap:5px;display:grid}.find-bar__row[data-v-120d7f24]{align-items:center;gap:1px;display:flex}.find-bar__input[data-v-120d7f24]{width:220px;margin-right:4px}.find-bar__count[data-v-120d7f24]{color:var(--nuvra-text-muted);font-variant-numeric:tabular-nums;font-size:11px}.find-bar__chevron[data-v-120d7f24]{transition:transform .15s}.is-active>.find-bar__chevron[data-v-120d7f24]{transform:rotate(90deg)}.find-bar__text-button[data-v-120d7f24]{padding:0 8px;font-size:12px}@container (width<=560px){.find-bar[data-v-120d7f24]{left:8px;right:8px}.find-bar__rows[data-v-120d7f24]{flex:auto;min-width:0}.find-bar__input[data-v-120d7f24]{flex:auto;width:auto}}.status-bar[data-v-53a08477]{border-top:1px solid var(--nuvra-border-lighter);min-height:32px;color:var(--nuvra-text-muted);background:var(--nuvra-bg);-webkit-user-select:none;user-select:none;flex:none;justify-content:space-between;align-items:center;gap:12px;padding:0 6px 0 12px;font-size:12px;display:flex}.status-bar__info[data-v-53a08477]{white-space:nowrap;gap:14px;min-width:0;display:flex;overflow:hidden}.is-limit[data-v-53a08477]{color:var(--nuvra-color-danger);font-weight:600}.status-bar__controls[data-v-53a08477]{flex:none;align-items:center;gap:1px;display:flex}.status-bar .doc-tb-button[data-v-53a08477]{min-width:24px;height:24px;font-size:12px}.status-bar__segmented[data-v-53a08477]{background:var(--nuvra-fill);border-radius:7px;margin-right:6px;padding:2px;display:flex}.status-bar__segmented .doc-tb-button[data-v-53a08477]{height:20px}.status-bar__segmented .doc-tb-button.is-active[data-v-53a08477]{background:var(--nuvra-bg);box-shadow:0 1px 2px #1018281f}.status-bar__slider[data-v-53a08477]{--slider-line:var(--nuvra-text-placeholder);--slider-thumb:var(--nuvra-text);cursor:pointer;background:linear-gradient(var(--slider-line), var(--slider-line)) calc(2px + (100% - 4px) * var(--v469880fc)) 50% / 1px 8px no-repeat, linear-gradient(var(--slider-line), var(--slider-line)) 0 50% / 100% 1px no-repeat;appearance:none;width:100px;height:16px;margin:0 2px;padding:0}.status-bar__slider[data-v-53a08477]:focus{outline:none}.status-bar__slider[data-v-53a08477]::-webkit-slider-runnable-track{background:0 0;height:16px}.status-bar__slider[data-v-53a08477]::-moz-range-track{background:0 0;height:16px}.status-bar__slider[data-v-53a08477]::-webkit-slider-thumb{background:var(--slider-thumb);appearance:none;border:none;border-radius:1px;width:4px;height:12px;margin-top:2px;transition:background-color .15s}.status-bar__slider[data-v-53a08477]::-moz-range-thumb{background:var(--slider-thumb);border:none;border-radius:1px;width:4px;height:12px;transition:background-color .15s}.status-bar__slider[data-v-53a08477]:hover,.status-bar__slider[data-v-53a08477]:active{--slider-thumb:var(--nuvra-color-primary)}.status-bar__slider[data-v-53a08477]:focus-visible::-webkit-slider-thumb{outline:2px solid var(--nuvra-color-primary-border);outline-offset:1px}.status-bar__slider[data-v-53a08477]:focus-visible::-moz-range-thumb{outline:2px solid var(--nuvra-color-primary-border);outline-offset:1px}.status-bar .status-bar__zoom-step[data-v-53a08477]{min-width:20px;height:20px;padding:0}.status-bar__zoom[data-v-53a08477]{font-variant-numeric:tabular-nums;min-width:40px}@container (width<=560px){.status-bar__slider[data-v-53a08477],.status-bar__segmented[data-v-53a08477]{display:none}}.doc-popover[data-v-9be14722],.doc-popover__reference[data-v-9be14722]{align-items:center;display:inline-flex}.doc-popover__panel[data-v-9be14722]{z-index:3000;box-sizing:border-box;padding:var(--doc-popover-padding,10px);border:1px solid var(--nuvra-border-light);color:var(--nuvra-text);background:var(--nuvra-bg-overlay);box-shadow:var(--nuvra-shadow);text-align:left;border-radius:10px;margin:0;font-size:14px;line-height:1.4;position:fixed;inset:auto;overflow:auto}.doc-popover__panel[data-v-9be14722]:not(.is-open){display:none}.color-picker[data-v-5a7a7d2d]{align-items:center;display:inline-flex}.color-picker__apply[data-v-5a7a7d2d]{min-width:26px;padding-bottom:3px;position:relative}.color-picker__letter[data-v-5a7a7d2d]{font-family:Georgia,serif;font-size:15px;font-weight:700}.color-picker__bar[data-v-5a7a7d2d]{border-radius:1px;height:3px;position:absolute;bottom:4px;left:6px;right:6px;box-shadow:inset 0 0 0 1px #0000001f}.palette[data-v-5a7a7d2d]{gap:8px;display:grid}.palette__reset[data-v-5a7a7d2d],.palette__custom[data-v-5a7a7d2d]{height:28px;color:var(--nuvra-text);font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:6px;align-items:center;gap:8px;padding:0 6px;font-size:13px;display:flex}.palette__reset[data-v-5a7a7d2d]:hover,.palette__custom[data-v-5a7a7d2d]:hover{background:var(--nuvra-fill)}.palette__reset-swatch[data-v-5a7a7d2d]{box-sizing:border-box;border:1px solid var(--nuvra-border);border-radius:3px;width:16px;height:16px}.palette__reset-swatch.is-text[data-v-5a7a7d2d]{background:#1f2328}.palette__reset-swatch.is-highlight[data-v-5a7a7d2d]{background:linear-gradient(to top right,#fff calc(50% - 1px),#e11d48 50%,#fff calc(50% + 1px))}.palette__grid[data-v-5a7a7d2d]{grid-template-columns:repeat(10,18px);justify-content:space-between;gap:3px;display:grid}.palette__swatch[data-v-5a7a7d2d]{cursor:pointer;border:1px solid #0000001f;border-radius:3px;width:18px;height:18px;padding:0;transition:transform .1s}.palette__swatch[data-v-5a7a7d2d]:hover{transform:scale(1.15)}.palette__swatch.is-selected[data-v-5a7a7d2d]{box-shadow:0 0 0 2px #fff, 0 0 0 3.5px var(--nuvra-color-primary)}.palette__custom input[data-v-5a7a7d2d]{cursor:pointer;background:0 0;border:0;width:22px;height:22px;padding:0}.page-setup[data-v-ecee5398]{color:var(--nuvra-text);gap:12px;display:grid}.page-setup__section[data-v-ecee5398]{gap:6px;display:grid}.page-setup__section h4[data-v-ecee5398]{color:var(--nuvra-text-strong);margin:0;font-size:12px;font-weight:600}.page-setup__grid[data-v-ecee5398]{grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;display:grid}.page-setup__grid--sizes[data-v-ecee5398],.page-setup__grid--presets[data-v-ecee5398]{grid-template-columns:repeat(3,minmax(0,1fr))}.page-setup__chip[data-v-ecee5398]{border:1px solid var(--nuvra-border);min-width:0;color:inherit;font:inherit;text-align:left;cursor:pointer;background:0 0;border-radius:6px;flex-direction:column;align-items:flex-start;gap:1px;padding:5px 8px;font-size:12px;display:flex}.page-setup__chip[data-v-ecee5398]:hover{border-color:var(--nuvra-color-primary-border)}.page-setup__chip.is-active[data-v-ecee5398]{border-color:var(--nuvra-color-primary);color:var(--nuvra-color-primary);background:var(--nuvra-color-primary-soft)}.page-setup__chip--row[data-v-ecee5398]{flex-direction:row;align-items:center;gap:6px}.page-setup__chip small[data-v-ecee5398]{color:var(--nuvra-text-muted);white-space:nowrap;font-size:10px}.page-setup__caption[data-v-ecee5398]{color:var(--nuvra-text-muted);margin-top:4px;font-size:11px}.page-setup__field[data-v-ecee5398]{color:var(--nuvra-text-muted);gap:3px;font-size:11px;display:grid}.table-picker[data-v-7a30bfca]{gap:6px;display:grid}.table-picker__grid[data-v-7a30bfca]{grid-template-columns:repeat(10,16px);gap:3px;display:grid}.table-picker__cell[data-v-7a30bfca]{border:1px solid var(--nuvra-border);background:var(--nuvra-bg);cursor:pointer;border-radius:2px;width:16px;height:16px;padding:0}.table-picker__cell.is-active[data-v-7a30bfca]{border-color:var(--nuvra-color-primary);background:var(--nuvra-color-primary-muted)}.table-picker__size[data-v-7a30bfca]{color:var(--nuvra-text);text-align:center;font-size:12px}.doc-toolbar[data-v-ecc5f4de]{box-sizing:border-box;border-bottom:1px solid var(--nuvra-border-lighter);background:var(--nuvra-bg);scrollbar-width:thin;flex:none;align-items:center;gap:2px;min-height:40px;padding:5px 8px;display:flex;overflow-x:auto}.doc-toolbar__group[data-v-ecc5f4de]{flex:none;align-items:center;gap:1px;display:flex}.doc-toolbar__divider[data-v-ecc5f4de]{background:var(--nuvra-border-lighter);flex:0 0 1px;align-self:stretch;margin:4px 5px}.doc-toolbar__spacer[data-v-ecc5f4de]{flex:auto;min-width:8px}.doc-toolbar__block[data-v-ecc5f4de]{width:108px}.doc-toolbar__font[data-v-ecc5f4de]{width:118px}.doc-toolbar__size[data-v-ecc5f4de]{width:50px}.doc-toolbar[data-v-ecc5f4de] .doc-toolbar__size-menu{min-width:96px}.doc-toolbar__form[data-v-ecc5f4de]{gap:8px;display:grid}.doc-toolbar__field[data-v-ecc5f4de]{color:var(--nuvra-text-muted);gap:4px;font-size:12px;display:grid}.doc-toolbar__form-actions[data-v-ecc5f4de]{justify-content:flex-end;gap:6px;display:flex}.doc-toolbar__caption[data-v-ecc5f4de]{color:var(--nuvra-text-muted);text-align:center;font-size:11px}.doc-toolbar__inline-form[data-v-ecc5f4de]{gap:6px;display:flex}.doc-toolbar__characters[data-v-ecc5f4de]{grid-template-columns:repeat(9,minmax(0,1fr));gap:2px;display:grid}.doc-toolbar__characters button[data-v-ecc5f4de]{height:26px;color:inherit;cursor:pointer;background:0 0;border:0;border-radius:4px;padding:0;font-size:15px}.doc-toolbar__characters button[data-v-ecc5f4de]:hover{background:var(--nuvra-fill)}.doc-content{color:#1f2328;white-space:pre-wrap;overflow-wrap:break-word;tab-size:4;font-family:Times New Roman,Times,serif;font-size:12pt;line-height:1.5}.doc-content :is(p,h1,h2,h3,h4,h5,h6):not([dir]){unicode-bidi:plaintext}.doc-content p{margin:0 0 6pt}.doc-content h1,.doc-content h2,.doc-content h3,.doc-content h4,.doc-content h5,.doc-content h6{margin:0 0 6pt;padding-top:6pt;font-weight:700;line-height:1.25}.doc-content h1{font-size:20pt}.doc-content h2{font-size:16pt}.doc-content h3{font-size:14pt}.doc-content h4{font-size:12pt}.doc-content h5{font-size:11pt}.doc-content h6{font-size:10pt}.doc-content ul,.doc-content ol{margin:0 0 6pt;padding-left:24pt}.doc-content li>p{margin-bottom:2pt}.doc-content ul[data-type=taskList]{padding-left:2pt;list-style:none}.doc-content ul[data-type=taskList] li{align-items:flex-start;gap:6pt;display:flex}.doc-content ul[data-type=taskList] li>label{-webkit-user-select:none;user-select:none;flex:none;margin-top:.3em}.doc-content ul[data-type=taskList] li>div{flex:auto;min-width:0}.doc-content ul[data-type=taskList] li[data-checked=true]>div{color:#667085;text-decoration:line-through}.doc-content blockquote{color:#475467;border-left:3px solid #b3c5f5;margin:0 0 6pt;padding:2pt 0 2pt 12pt}.doc-content blockquote>p:last-child,.doc-content li>p:last-child,.doc-content td>p:last-child,.doc-content th>p:last-child{margin-bottom:0}.doc-content pre{white-space:pre-wrap;background:#f4f6f8;border-radius:4px;margin:0 0 6pt;padding:8pt 10pt;font-family:Consolas,Courier New,monospace;font-size:10pt;line-height:1.45}.doc-content code{background:#eef1f4;border-radius:3px;padding:1px 4px;font-family:Consolas,Courier New,monospace;font-size:.9em}.doc-content pre code{font-size:inherit;background:0 0;padding:0}.doc-content hr{border:0;border-bottom:1px solid #c4cad4;height:0;margin:0 0 6pt;padding-top:6pt}.doc-content a{color:#1d4ed8;text-decoration:underline}.doc-content mark{color:inherit;border-radius:2px;padding:0 1px}.doc-content img{max-width:100%;height:auto}.doc-content img[data-align=left]{margin:0 auto 6pt 0;display:block}.doc-content img[data-align=center]{margin:0 auto 6pt;display:block}.doc-content img[data-align=right]{margin:0 0 6pt auto;display:block}.doc-content table{border-collapse:collapse;table-layout:fixed;width:100%;margin:0 0 6pt}.doc-content td,.doc-content th{box-sizing:border-box;vertical-align:top;border:1px solid #8f99a8;min-width:1em;padding:3pt 5pt}.doc-content th{text-align:left;background:#f2f4f7;font-weight:700}.doc-content .doc-page-break{break-after:page;page-break-after:always;height:0}.document-editor{--nuvra-color-primary:#409eff;--nuvra-color-primary-hover:#79bbff;--nuvra-color-primary-border:#a0cfff;--nuvra-color-primary-muted:#c6e2ff;--nuvra-color-primary-soft:#ecf5ff;--nuvra-color-on-primary:#fff;--nuvra-color-danger:#f56c6c;--nuvra-color-danger-soft:#fef0f0;--nuvra-text-strong:#303133;--nuvra-text:#606266;--nuvra-text-muted:#909399;--nuvra-text-placeholder:#a8abb2;--nuvra-text-disabled:#c0c4cc;--nuvra-border:#dcdfe6;--nuvra-border-hover:#c0c4cc;--nuvra-border-light:#e4e7ed;--nuvra-border-lighter:#ebeef5;--nuvra-fill:#f5f7fa;--nuvra-bg:#fff;--nuvra-bg-overlay:#fff;--nuvra-shadow:0 0 12px #0000001f;--nuvra-fullscreen-z-index:2000}:where(.dark,[data-theme=dark]) .document-editor{--nuvra-color-primary-hover:#66b1ff;--nuvra-color-primary-border:#2a598a;--nuvra-color-primary-muted:#213d5b;--nuvra-color-primary-soft:#18222c;--nuvra-color-danger-soft:#2b1d1d;--nuvra-text-strong:#e5eaf3;--nuvra-text:#cfd3dc;--nuvra-text-muted:#a3a6ad;--nuvra-text-placeholder:#8d9095;--nuvra-text-disabled:#6c6e72;--nuvra-border:#4c4d4f;--nuvra-border-hover:#6c6e72;--nuvra-border-light:#414243;--nuvra-border-lighter:#363637;--nuvra-fill:#262727;--nuvra-bg:#141414;--nuvra-bg-overlay:#1d1e1f;--nuvra-shadow:0 0 12px #000000b8}.doc-tb-button{box-sizing:border-box;min-width:28px;height:28px;color:var(--nuvra-text);font:inherit;white-space:nowrap;cursor:pointer;background:0 0;border:0;border-radius:6px;flex:none;justify-content:center;align-items:center;gap:4px;padding:0 5px;font-size:13px;line-height:1;transition:background-color .12s,color .12s;display:inline-flex}.doc-tb-button:hover:not(:disabled){background:var(--nuvra-fill)}.doc-tb-button:focus-visible{outline:2px solid var(--nuvra-color-primary);outline-offset:-2px}.doc-tb-button.is-active{color:var(--nuvra-color-primary);background:var(--nuvra-color-primary-soft)}.doc-tb-button:disabled{color:var(--nuvra-text-disabled);cursor:not-allowed}.doc-tb-button--select{justify-content:space-between;padding:0 4px 0 7px}.doc-tb-button--caret{min-width:16px;padding:0 2px}.doc-tb-button__label{text-overflow:ellipsis;overflow:hidden}.doc-menu{--doc-popover-padding:4px}.doc-menu__items{min-width:168px;display:grid}.doc-menu__item{box-sizing:border-box;width:100%;color:var(--nuvra-text);font:inherit;text-align:left;white-space:nowrap;cursor:pointer;background:0 0;border:0;border-radius:6px;outline:none;align-items:center;gap:8px;padding:5px 12px 5px 8px;font-size:13px;line-height:20px;display:flex}.doc-menu__item:hover,.doc-menu__item:focus-visible{color:var(--nuvra-color-primary);background:var(--nuvra-color-primary-soft)}.doc-menu__item.is-selected{color:var(--nuvra-color-primary);font-weight:600}.doc-menu__divider{background:var(--nuvra-border-lighter);height:1px;margin:4px 0}.doc-menu__hint{color:var(--nuvra-text-placeholder);margin-left:auto;padding-left:20px;font-size:11px;font-weight:400}.doc-menu__h1{font-size:18px;font-weight:700}.doc-menu__h2{font-size:16px;font-weight:700}.doc-menu__h3{font-size:15px;font-weight:700}.doc-menu__h4{font-size:14px;font-weight:700}.doc-input{box-sizing:border-box;border:1px solid var(--nuvra-border);width:100%;min-width:0;height:24px;color:var(--nuvra-text);background:var(--nuvra-bg);font:inherit;border-radius:4px;outline:none;margin:0;padding:0 7px;font-size:12px;transition:border-color .12s}.doc-input::placeholder{color:var(--nuvra-text-placeholder)}.doc-input:hover{border-color:var(--nuvra-border-hover)}.doc-input:focus,.doc-input:focus-within{border-color:var(--nuvra-color-primary)}.doc-input--affix{align-items:center;gap:6px;display:inline-flex}.doc-input--affix input{min-width:0;height:100%;color:inherit;font:inherit;background:0 0;border:0;outline:none;flex:auto;margin:0;padding:0}.doc-input--affix input::placeholder{color:var(--nuvra-text-placeholder)}.doc-btn{box-sizing:border-box;border:1px solid var(--nuvra-border);height:24px;color:var(--nuvra-text);background:var(--nuvra-bg);font:inherit;white-space:nowrap;cursor:pointer;border-radius:4px;flex:none;justify-content:center;align-items:center;gap:5px;margin:0;padding:0 11px;font-size:12px;line-height:1;transition:background-color .12s,border-color .12s,color .12s;display:inline-flex}.doc-btn:hover:not(:disabled){border-color:var(--nuvra-color-primary-muted);color:var(--nuvra-color-primary);background:var(--nuvra-color-primary-soft)}.doc-btn:focus-visible{outline:2px solid var(--nuvra-color-primary-border);outline-offset:1px}.doc-btn:disabled{border-color:var(--nuvra-border-lighter);color:var(--nuvra-text-placeholder);cursor:not-allowed}.doc-btn--primary{border-color:var(--nuvra-color-primary);color:var(--nuvra-color-on-primary);background:var(--nuvra-color-primary)}.doc-btn--primary:hover:not(:disabled){border-color:var(--nuvra-color-primary-hover);color:var(--nuvra-color-on-primary);background:var(--nuvra-color-primary-hover)}.doc-btn--primary:disabled{border-color:var(--nuvra-color-primary-border);color:var(--nuvra-color-on-primary);background:var(--nuvra-color-primary-border)}.doc-btn--danger-text{color:var(--nuvra-color-danger);background:0 0;border-color:#0000}.doc-btn--danger-text:hover:not(:disabled){color:var(--nuvra-color-danger);background:var(--nuvra-color-danger-soft);border-color:#0000}.doc-checkbox{color:var(--nuvra-text);cursor:pointer;-webkit-user-select:none;user-select:none;align-items:center;gap:6px;font-size:12px;display:inline-flex}.doc-checkbox input{width:13px;height:13px;accent-color:var(--nuvra-color-primary);cursor:pointer;margin:0}.doc-spin{animation:1s linear infinite doc-spin}@keyframes doc-spin{to{transform:rotate(360deg)}}.doc-canvas .doc-content{--doc-placeholder:""}.doc-canvas .doc-content.is-empty>p:first-child:before{float:left;color:#98a2b3;content:var(--doc-placeholder);pointer-events:none;height:0}.doc-canvas .doc-content .doc-page-break{cursor:default;-webkit-user-select:none;user-select:none;height:18px;margin-bottom:6pt;position:relative}.doc-canvas .doc-content .doc-page-break:before{content:"";border-top:1px dashed #98a2b3;position:absolute;top:50%;left:0;right:0}.doc-canvas .doc-content .doc-page-break:after{color:#667085;letter-spacing:.04em;text-transform:uppercase;content:var(--page-break-label);background:#fff;padding:0 8px;font:10px/16px system-ui,sans-serif;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.doc-canvas .doc-content td,.doc-canvas .doc-content th{position:relative}.doc-canvas .doc-content .doc-cell-selected:after{content:"";pointer-events:none;background:#3b82f629;position:absolute;inset:0}.doc-canvas .doc-content.has-cell-selection ::selection{background:0 0}.doc-canvas .doc-content.is-column-resize,.doc-canvas .doc-content.is-column-resize *{cursor:col-resize}.doc-canvas .doc-content ul[data-type=taskList] input[type=checkbox]{cursor:pointer}.doc-canvas .doc-content a{cursor:text}::highlight(doc-search){background-color:#facc1573}::highlight(doc-search-current){background-color:#f973168c}.document-editor[data-v-e22a5e8e]{--doc-editor-canvas-padding:50px;--doc-editor-height:760px;--doc-editor-min-height:240px;--doc-editor-max-height:600px;box-sizing:border-box;width:100%;min-width:0;height:var(--doc-editor-height);border:1px solid var(--nuvra-border);background:var(--nuvra-bg);border-radius:10px;flex-direction:column;min-height:360px;transition:border-color .16s;display:flex;position:relative;overflow:hidden;container-type:inline-size}.document-editor[data-v-e22a5e8e]:focus-within{border-color:var(--nuvra-color-primary-border)}.document-editor.is-auto-height[data-v-e22a5e8e]{height:auto;min-height:0}.document-editor.is-fullscreen[data-v-e22a5e8e]{z-index:var(--nuvra-fullscreen-z-index);border:0;border-radius:0;height:100dvh;position:fixed;inset:0}.document-editor__body[data-v-e22a5e8e]{flex-direction:column;flex:auto;min-height:0;display:flex;position:relative}.document-editor__source[data-v-e22a5e8e]{box-sizing:border-box;color:#1f2328;resize:none;tab-size:2;background:#fbfcfd;border:0;outline:none;flex:auto;min-height:0;margin:0;padding:16px 20px;font:13px/1.6 ui-monospace,SFMono-Regular,Consolas,monospace}.document-editor__uploading[data-v-e22a5e8e]{color:#fff;pointer-events:none;background:#101828cc;border-radius:999px;padding:6px 12px;font-size:12px;position:absolute;bottom:12px;left:50%;transform:translate(-50%)}
1
+ .doc-icon[data-v-4e391eda]{flex:none}.doc-bubble[data-v-41a7aa00]{z-index:2100;box-sizing:border-box;border:1px solid var(--nuvra-border-light);color:var(--nuvra-text);background:var(--nuvra-bg-overlay);border-radius:8px;align-items:center;gap:1px;margin:0;padding:3px;display:flex;position:fixed;inset:auto;overflow:visible;box-shadow:0 6px 20px #10182829}.doc-bubble.is-hidden[data-v-41a7aa00]{visibility:hidden}.doc-bubble__divider[data-v-41a7aa00]{background:var(--nuvra-border-lighter);flex:0 0 1px;align-self:stretch;margin:3px 4px}.doc-bubble .doc-tb-button.is-danger[data-v-41a7aa00]:hover:not(:disabled){color:var(--nuvra-color-danger);background:var(--nuvra-color-danger-soft)}.doc-bubble__link[data-v-41a7aa00]{max-width:260px;color:var(--nuvra-color-primary);align-items:center;gap:5px;padding:0 6px;font-size:12px;text-decoration:none;display:inline-flex}.doc-bubble__link span[data-v-41a7aa00]{text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.doc-bubble__form[data-v-41a7aa00]{gap:4px;width:280px;display:flex}.object-overlay[data-v-7da0d742]{z-index:3;pointer-events:none;position:absolute;inset:0}.object-overlay__image[data-v-7da0d742]{box-sizing:border-box;outline-offset:1px;outline:2px solid #3b82f6;position:absolute}.object-overlay__handle[data-v-7da0d742]{box-sizing:border-box;pointer-events:auto;background:#fff;border:1.5px solid #3b82f6;border-radius:2px;width:10px;height:10px;position:absolute}.object-overlay__handle.is-top-left[data-v-7da0d742]{cursor:nwse-resize;top:-6px;left:-6px}.object-overlay__handle.is-top-right[data-v-7da0d742]{cursor:nesw-resize;top:-6px;right:-6px}.object-overlay__handle.is-bottom-left[data-v-7da0d742]{cursor:nesw-resize;bottom:-6px;left:-6px}.object-overlay__handle.is-bottom-right[data-v-7da0d742]{cursor:nwse-resize;bottom:-6px;right:-6px}.object-overlay__size[data-v-7da0d742]{color:#fff;background:#101828bf;border-radius:4px;padding:2px 6px;font:11px/16px system-ui,sans-serif;position:absolute;bottom:4px;right:4px}.object-overlay__guide[data-v-7da0d742]{border-left:1px dashed #3b82f6;width:0;position:absolute}.doc-ruler[data-v-5b73e4e7]{box-sizing:border-box;border:1px solid var(--nuvra-border-lighter);background:var(--nuvra-fill);-webkit-user-select:none;user-select:none;border-radius:4px;height:26px;position:relative}.doc-ruler__text-area[data-v-5b73e4e7]{background:var(--nuvra-bg);position:absolute;top:0;bottom:0}.doc-ruler__tick[data-v-5b73e4e7]{background:var(--nuvra-text-placeholder);pointer-events:none;width:1px;height:4px;margin-top:-2px;position:absolute;top:50%}.doc-ruler__tick.is-labelled[data-v-5b73e4e7]{background:0 0}.doc-ruler__tick i[data-v-5b73e4e7]{color:var(--nuvra-text-muted);font:9px/1 system-ui,sans-serif;position:absolute;top:-5px;left:50%;transform:translate(-50%)}.doc-ruler__handle[data-v-5b73e4e7]{cursor:ew-resize;background:0 0;border:0;width:14px;height:8px;padding:0;position:absolute;transform:translate(-7px)}.doc-ruler__handle[data-v-5b73e4e7]:disabled{cursor:default}.doc-ruler__handle[data-v-5b73e4e7]:before{background:var(--nuvra-color-primary);content:"";opacity:.7;position:absolute;inset:1px 2px}.doc-ruler__handle[data-v-5b73e4e7]:hover:before,.doc-ruler__handle.is-dragging[data-v-5b73e4e7]:before{opacity:1}.doc-ruler__handle--first-line[data-v-5b73e4e7]{top:0}.doc-ruler__handle--first-line[data-v-5b73e4e7]:before{clip-path:polygon(0 0,100% 0,50% 100%)}.doc-ruler__handle--indent-left[data-v-5b73e4e7],.doc-ruler__handle--indent-right[data-v-5b73e4e7]{bottom:0}.doc-ruler__handle--indent-left[data-v-5b73e4e7]:before,.doc-ruler__handle--indent-right[data-v-5b73e4e7]:before{clip-path:polygon(50% 0,100% 100%,0 100%)}.doc-ruler__handle--margin[data-v-5b73e4e7]{height:8px;top:8px}.doc-ruler__handle--margin[data-v-5b73e4e7]:before{background:var(--nuvra-text-muted);border-radius:1px;inset:0 6px}.doc-ruler__guide[data-v-5b73e4e7]{background:var(--nuvra-color-primary);opacity:.5;pointer-events:none;width:1px;height:60vh;position:absolute;top:100%}.doc-canvas[data-v-8a9106da]{box-sizing:border-box;min-height:0;padding:var(--doc-editor-canvas-padding);overscroll-behavior:contain;background:#e9ebef;flex:auto;position:relative;overflow:auto}.doc-canvas.is-auto[data-v-8a9106da]{min-height:var(--doc-editor-min-height);max-height:var(--doc-editor-max-height);flex:none}.doc-canvas__sizer[data-v-8a9106da]{margin:0 auto;position:relative}.doc-canvas__ruler[data-v-8a9106da]{z-index:3;margin:0 auto 10px;position:sticky;top:0}.doc-canvas__stage[data-v-8a9106da]{--page-height:1123px;--pages-height:1123px;--margin-top:96px;--margin-right:96px;--margin-bottom:96px;--margin-left:96px;--page-break-label:"";transform-origin:0 0;position:absolute;top:0;left:0}.doc-canvas.is-web .doc-canvas__stage[data-v-8a9106da]{background:#fff;box-shadow:0 0 0 1px #1018280f,0 1px 4px #10182814}.doc-canvas__sheets[data-v-8a9106da]{pointer-events:none;position:absolute;inset:0}.doc-canvas__sheet[data-v-8a9106da]{width:100%;height:var(--page-height);background:#fff;position:absolute;left:0;box-shadow:0 0 0 1px #1018280f,0 2px 8px #1018281a}.doc-canvas__page-number[data-v-8a9106da]{right:0;bottom:calc(var(--margin-bottom) / 2 - 8px);color:#98a2b3;text-align:center;font:11px/16px system-ui,sans-serif;position:absolute;left:0}.doc-canvas__watermark[data-v-8a9106da]{letter-spacing:.06em;opacity:.16;text-transform:uppercase;white-space:nowrap;justify-content:center;align-items:center;font-family:Times New Roman,Times,serif;font-weight:700;line-height:1;display:flex;position:absolute;inset:0;overflow:hidden}.doc-canvas__running[data-v-8a9106da]{right:var(--margin-right);left:var(--margin-left);color:#475467;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:12px;font:10pt/1.4 Times New Roman,Times,serif;display:grid;position:absolute}.doc-canvas__running span[data-v-8a9106da]{text-overflow:ellipsis;white-space:nowrap;min-width:0;overflow:hidden}.doc-canvas__running span[data-v-8a9106da]:nth-child(2){text-align:center}.doc-canvas__running span[data-v-8a9106da]:nth-child(3){text-align:right}.doc-canvas__running--header[data-v-8a9106da]{top:max(6px, calc(var(--margin-top) / 2 - 8px))}.doc-canvas__running--footer[data-v-8a9106da]{bottom:max(6px, calc(var(--margin-bottom) / 2 - 8px))}.doc-canvas__content[data-v-8a9106da]{box-sizing:border-box;min-height:inherit;caret-color:#1f2328;outline:none;position:relative}.doc-canvas.is-page .doc-canvas__content[data-v-8a9106da]{min-height:var(--pages-height);padding:var(--margin-top) var(--margin-right) var(--margin-bottom) var(--margin-left)}.doc-canvas.is-web .doc-canvas__content[data-v-8a9106da]{padding:40px 56px}.doc-canvas.is-auto.is-web .doc-canvas__content[data-v-8a9106da]{padding:16px 20px}.doc-context-menu[data-v-cbca2839]{z-index:3000;box-sizing:border-box;max-height:80vh;padding:var(--doc-popover-padding,4px);border:1px solid var(--nuvra-border-light);color:var(--nuvra-text);background:var(--nuvra-bg-overlay);box-shadow:var(--nuvra-shadow);text-align:left;border-radius:10px;margin:0;font-size:14px;line-height:1.4;position:fixed;inset:auto;overflow:auto}.doc-context-menu[data-v-cbca2839]:not(.is-open){display:none}.find-bar[data-v-120d7f24]{z-index:5;border:1px solid var(--nuvra-border-light);background:var(--nuvra-bg-overlay);box-shadow:var(--nuvra-shadow);border-radius:10px;align-items:flex-start;gap:2px;padding:5px;display:flex;position:absolute;top:8px;right:20px}.find-bar__rows[data-v-120d7f24]{gap:5px;display:grid}.find-bar__row[data-v-120d7f24]{align-items:center;gap:1px;display:flex}.find-bar__input[data-v-120d7f24]{width:220px;margin-right:4px}.find-bar__count[data-v-120d7f24]{color:var(--nuvra-text-muted);font-variant-numeric:tabular-nums;font-size:11px}.find-bar__chevron[data-v-120d7f24]{transition:transform .15s}.is-active>.find-bar__chevron[data-v-120d7f24]{transform:rotate(90deg)}.find-bar__text-button[data-v-120d7f24]{padding:0 8px;font-size:12px}@container (width<=560px){.find-bar[data-v-120d7f24]{left:8px;right:8px}.find-bar__rows[data-v-120d7f24]{flex:auto;min-width:0}.find-bar__input[data-v-120d7f24]{flex:auto;width:auto}}.status-bar[data-v-53a08477]{border-top:1px solid var(--nuvra-border-lighter);min-height:32px;color:var(--nuvra-text-muted);background:var(--nuvra-bg);-webkit-user-select:none;user-select:none;flex:none;justify-content:space-between;align-items:center;gap:12px;padding:0 6px 0 12px;font-size:12px;display:flex}.status-bar__info[data-v-53a08477]{white-space:nowrap;gap:14px;min-width:0;display:flex;overflow:hidden}.is-limit[data-v-53a08477]{color:var(--nuvra-color-danger);font-weight:600}.status-bar__controls[data-v-53a08477]{flex:none;align-items:center;gap:1px;display:flex}.status-bar .doc-tb-button[data-v-53a08477]{min-width:24px;height:24px;font-size:12px}.status-bar__segmented[data-v-53a08477]{background:var(--nuvra-fill);border-radius:7px;margin-right:6px;padding:2px;display:flex}.status-bar__segmented .doc-tb-button[data-v-53a08477]{height:20px}.status-bar__segmented .doc-tb-button.is-active[data-v-53a08477]{background:var(--nuvra-bg);box-shadow:0 1px 2px #1018281f}.status-bar__slider[data-v-53a08477]{--slider-line:var(--nuvra-text-placeholder);--slider-thumb:var(--nuvra-text);cursor:pointer;background:linear-gradient(var(--slider-line), var(--slider-line)) calc(2px + (100% - 4px) * var(--v469880fc)) 50% / 1px 8px no-repeat, linear-gradient(var(--slider-line), var(--slider-line)) 0 50% / 100% 1px no-repeat;appearance:none;width:100px;height:16px;margin:0 2px;padding:0}.status-bar__slider[data-v-53a08477]:focus{outline:none}.status-bar__slider[data-v-53a08477]::-webkit-slider-runnable-track{background:0 0;height:16px}.status-bar__slider[data-v-53a08477]::-moz-range-track{background:0 0;height:16px}.status-bar__slider[data-v-53a08477]::-webkit-slider-thumb{background:var(--slider-thumb);appearance:none;border:none;border-radius:1px;width:4px;height:12px;margin-top:2px;transition:background-color .15s}.status-bar__slider[data-v-53a08477]::-moz-range-thumb{background:var(--slider-thumb);border:none;border-radius:1px;width:4px;height:12px;transition:background-color .15s}.status-bar__slider[data-v-53a08477]:hover,.status-bar__slider[data-v-53a08477]:active{--slider-thumb:var(--nuvra-color-primary)}.status-bar__slider[data-v-53a08477]:focus-visible::-webkit-slider-thumb{outline:2px solid var(--nuvra-color-primary-border);outline-offset:1px}.status-bar__slider[data-v-53a08477]:focus-visible::-moz-range-thumb{outline:2px solid var(--nuvra-color-primary-border);outline-offset:1px}.status-bar .status-bar__zoom-step[data-v-53a08477]{min-width:20px;height:20px;padding:0}.status-bar__zoom[data-v-53a08477]{font-variant-numeric:tabular-nums;min-width:40px}@container (width<=560px){.status-bar__slider[data-v-53a08477],.status-bar__segmented[data-v-53a08477]{display:none}}.doc-popover[data-v-9be14722],.doc-popover__reference[data-v-9be14722]{align-items:center;display:inline-flex}.doc-popover__panel[data-v-9be14722]{z-index:3000;box-sizing:border-box;padding:var(--doc-popover-padding,10px);border:1px solid var(--nuvra-border-light);color:var(--nuvra-text);background:var(--nuvra-bg-overlay);box-shadow:var(--nuvra-shadow);text-align:left;border-radius:10px;margin:0;font-size:14px;line-height:1.4;position:fixed;inset:auto;overflow:auto}.doc-popover__panel[data-v-9be14722]:not(.is-open){display:none}.color-picker[data-v-e2d0cbb7]{align-items:center;display:inline-flex}.color-picker__apply[data-v-e2d0cbb7]{min-width:26px;padding-bottom:3px;position:relative}.color-picker__letter[data-v-e2d0cbb7]{font-family:Georgia,serif;font-size:15px;font-weight:700}.color-picker__bar[data-v-e2d0cbb7]{border-radius:1px;height:3px;position:absolute;bottom:4px;left:6px;right:6px;box-shadow:inset 0 0 0 1px #0000001f}.palette[data-v-e2d0cbb7]{gap:8px;display:grid}.palette__reset[data-v-e2d0cbb7],.palette__custom[data-v-e2d0cbb7]{height:28px;color:var(--nuvra-text);font:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:6px;align-items:center;gap:8px;padding:0 6px;font-size:13px;display:flex}.palette__reset[data-v-e2d0cbb7]:hover,.palette__custom[data-v-e2d0cbb7]:hover{background:var(--nuvra-fill)}.palette__reset-swatch[data-v-e2d0cbb7]{box-sizing:border-box;border:1px solid var(--nuvra-border);border-radius:3px;width:16px;height:16px}.palette__reset-swatch.is-text[data-v-e2d0cbb7]{background:#1f2328}.palette__reset-swatch.is-highlight[data-v-e2d0cbb7]{background:linear-gradient(to top right,#fff calc(50% - 1px),#e11d48 50%,#fff calc(50% + 1px))}.palette__grid[data-v-e2d0cbb7]{grid-template-columns:repeat(10,18px);justify-content:space-between;gap:3px;display:grid}.palette__swatch[data-v-e2d0cbb7]{cursor:pointer;border:1px solid #0000001f;border-radius:3px;width:18px;height:18px;padding:0;transition:transform .1s}.palette__swatch[data-v-e2d0cbb7]:hover{transform:scale(1.15)}.palette__swatch.is-selected[data-v-e2d0cbb7]{box-shadow:0 0 0 2px #fff, 0 0 0 3.5px var(--nuvra-color-primary)}.palette__custom input[data-v-e2d0cbb7]{cursor:pointer;background:0 0;border:0;width:22px;height:22px;padding:0}.header-footer[data-v-5b4d6d09]{color:var(--nuvra-text);gap:12px;display:grid}.header-footer__section[data-v-5b4d6d09]{gap:6px;display:grid}.header-footer__section h4[data-v-5b4d6d09]{color:var(--nuvra-text-strong);margin:0;font-size:12px;font-weight:600}.header-footer__grid[data-v-5b4d6d09]{grid-template-columns:repeat(3,minmax(0,1fr));gap:6px;display:grid}.header-footer__field[data-v-5b4d6d09]{color:var(--nuvra-text-muted);gap:3px;font-size:11px;display:grid}.header-footer__tokens[data-v-5b4d6d09]{flex-wrap:wrap;align-items:center;gap:4px;display:flex}.header-footer__actions[data-v-5b4d6d09]{justify-content:space-between;align-items:center;gap:8px;display:flex}.header-footer__caption[data-v-5b4d6d09]{color:var(--nuvra-text-muted);font-size:11px}.page-setup[data-v-3b1e7d9c]{color:var(--nuvra-text);gap:12px;display:grid}.page-setup__section[data-v-3b1e7d9c]{gap:6px;display:grid}.page-setup__section h4[data-v-3b1e7d9c]{color:var(--nuvra-text-strong);margin:0;font-size:12px;font-weight:600}.page-setup__grid[data-v-3b1e7d9c]{grid-template-columns:repeat(2,minmax(0,1fr));gap:6px;display:grid}.page-setup__grid--sizes[data-v-3b1e7d9c],.page-setup__grid--presets[data-v-3b1e7d9c]{grid-template-columns:repeat(3,minmax(0,1fr))}.page-setup__chip[data-v-3b1e7d9c]{border:1px solid var(--nuvra-border);min-width:0;color:inherit;font:inherit;text-align:left;cursor:pointer;background:0 0;border-radius:6px;flex-direction:column;align-items:flex-start;gap:1px;padding:5px 8px;font-size:12px;display:flex}.page-setup__chip[data-v-3b1e7d9c]:hover{border-color:var(--nuvra-color-primary-border)}.page-setup__chip.is-active[data-v-3b1e7d9c]{border-color:var(--nuvra-color-primary);color:var(--nuvra-color-primary);background:var(--nuvra-color-primary-soft)}.page-setup__chip--row[data-v-3b1e7d9c]{flex-direction:row;align-items:center;gap:6px}.page-setup__chip small[data-v-3b1e7d9c]{color:var(--nuvra-text-muted);white-space:nowrap;font-size:10px}.page-setup__caption[data-v-3b1e7d9c]{color:var(--nuvra-text-muted);margin-top:4px;font-size:11px}.page-setup__field[data-v-3b1e7d9c]{color:var(--nuvra-text-muted);gap:3px;font-size:11px;display:grid}.page-setup__color[data-v-3b1e7d9c]{height:28px;padding:2px}.page-setup__checkbox[data-v-3b1e7d9c]{align-self:end;padding-bottom:4px}.table-picker[data-v-7a30bfca]{gap:6px;display:grid}.table-picker__grid[data-v-7a30bfca]{grid-template-columns:repeat(10,16px);gap:3px;display:grid}.table-picker__cell[data-v-7a30bfca]{border:1px solid var(--nuvra-border);background:var(--nuvra-bg);cursor:pointer;border-radius:2px;width:16px;height:16px;padding:0}.table-picker__cell.is-active[data-v-7a30bfca]{border-color:var(--nuvra-color-primary);background:var(--nuvra-color-primary-muted)}.table-picker__size[data-v-7a30bfca]{color:var(--nuvra-text);text-align:center;font-size:12px}.doc-toolbar[data-v-bdbd22d4]{box-sizing:border-box;border-bottom:1px solid var(--nuvra-border-lighter);background:var(--nuvra-bg);scrollbar-width:thin;flex:none;align-items:center;gap:2px;min-height:40px;padding:5px 8px;display:flex;overflow-x:auto}.doc-toolbar__group[data-v-bdbd22d4]{flex:none;align-items:center;gap:1px;display:flex}.doc-toolbar__divider[data-v-bdbd22d4]{background:var(--nuvra-border-lighter);flex:0 0 1px;align-self:stretch;margin:4px 5px}.doc-toolbar__spacer[data-v-bdbd22d4]{flex:auto;min-width:8px}.doc-toolbar__group--end[data-v-bdbd22d4]{background:var(--nuvra-bg);padding-left:6px;position:sticky;right:0}.doc-toolbar__block[data-v-bdbd22d4]{width:108px}.doc-toolbar__font[data-v-bdbd22d4]{width:118px}.doc-toolbar__size[data-v-bdbd22d4]{text-align:center;width:44px;height:28px;padding:0 4px}.doc-toolbar[data-v-bdbd22d4] .doc-toolbar__size-menu{min-width:96px}.doc-toolbar__form[data-v-bdbd22d4]{gap:8px;display:grid}.doc-toolbar__field[data-v-bdbd22d4]{color:var(--nuvra-text-muted);gap:4px;font-size:12px;display:grid}.doc-toolbar__form-actions[data-v-bdbd22d4]{justify-content:flex-end;gap:6px;display:flex}.doc-toolbar__caption[data-v-bdbd22d4]{color:var(--nuvra-text-muted);text-align:center;font-size:11px}.doc-toolbar__inline-form[data-v-bdbd22d4]{gap:6px;display:flex}.doc-toolbar__characters[data-v-bdbd22d4]{grid-template-columns:repeat(9,minmax(0,1fr));gap:2px;display:grid}.doc-toolbar__characters button[data-v-bdbd22d4]{height:26px;color:inherit;cursor:pointer;background:0 0;border:0;border-radius:4px;padding:0;font-size:15px}.doc-toolbar__characters button[data-v-bdbd22d4]:hover{background:var(--nuvra-fill)}.doc-content{color:#1f2328;white-space:pre-wrap;overflow-wrap:break-word;tab-size:4;font-family:Times New Roman,Times,serif;font-size:12pt;line-height:1.5}.doc-content :is(p,h1,h2,h3,h4,h5,h6):not([dir]){unicode-bidi:plaintext}.doc-content p{margin:0 0 6pt}.doc-content h1,.doc-content h2,.doc-content h3,.doc-content h4,.doc-content h5,.doc-content h6{margin:0 0 6pt;padding-top:6pt;font-weight:700;line-height:1.25}.doc-content h1{font-size:20pt}.doc-content h2{font-size:16pt}.doc-content h3{font-size:14pt}.doc-content h4{font-size:12pt}.doc-content h5{font-size:11pt}.doc-content h6{font-size:10pt}.doc-content ul,.doc-content ol{margin:0 0 6pt;padding-left:24pt}.doc-content li>p{margin-bottom:2pt}.doc-content ul[data-type=taskList]{padding-left:2pt;list-style:none}.doc-content ul[data-type=taskList] li{align-items:flex-start;gap:6pt;display:flex}.doc-content ul[data-type=taskList] li>label{-webkit-user-select:none;user-select:none;flex:none;margin-top:.3em}.doc-content ul[data-type=taskList] li>div{flex:auto;min-width:0}.doc-content ul[data-type=taskList] li[data-checked=true]>div{color:#667085;text-decoration:line-through}.doc-content blockquote{color:#475467;border-left:3px solid #b3c5f5;margin:0 0 6pt;padding:2pt 0 2pt 12pt}.doc-content blockquote>p:last-child,.doc-content li>p:last-child,.doc-content td>p:last-child,.doc-content th>p:last-child{margin-bottom:0}.doc-content pre{white-space:pre-wrap;background:#f4f6f8;border-radius:4px;margin:0 0 6pt;padding:8pt 10pt;font-family:Consolas,Courier New,monospace;font-size:10pt;line-height:1.45}.doc-content code{background:#eef1f4;border-radius:3px;padding:1px 4px;font-family:Consolas,Courier New,monospace;font-size:.9em}.doc-content pre code{font-size:inherit;background:0 0;padding:0}.doc-content hr{border:0;border-bottom:1px solid #c4cad4;height:0;margin:0 0 6pt;padding-top:6pt}.doc-content a{color:#1d4ed8;text-decoration:underline}.doc-content mark{color:inherit;border-radius:2px;padding:0 1px}.doc-content img{max-width:100%;height:auto}.doc-content img[data-align=left]{margin:0 auto 6pt 0;display:block}.doc-content img[data-align=center]{margin:0 auto 6pt;display:block}.doc-content img[data-align=right]{margin:0 0 6pt auto;display:block}.doc-content table{border-collapse:collapse;table-layout:fixed;width:100%;margin:0 0 6pt}.doc-content td,.doc-content th{box-sizing:border-box;vertical-align:top;border:1px solid #8f99a8;min-width:1em;padding:3pt 5pt}.doc-content th{text-align:left;background:#f2f4f7;font-weight:700}.doc-content .doc-page-break{break-after:page;page-break-after:always;height:0}:where(.document-editor){--nuvra-color-primary:#409eff;--nuvra-color-primary-hover:#79bbff;--nuvra-color-primary-border:#a0cfff;--nuvra-color-primary-muted:#c6e2ff;--nuvra-color-primary-soft:#ecf5ff;--nuvra-color-on-primary:#fff;--nuvra-color-danger:#f56c6c;--nuvra-color-danger-soft:#fef0f0;--nuvra-text-strong:#303133;--nuvra-text:#606266;--nuvra-text-muted:#909399;--nuvra-text-placeholder:#a8abb2;--nuvra-text-disabled:#c0c4cc;--nuvra-border:#dcdfe6;--nuvra-border-hover:#c0c4cc;--nuvra-border-light:#e4e7ed;--nuvra-border-lighter:#ebeef5;--nuvra-fill:#f5f7fa;--nuvra-bg:#fff;--nuvra-bg-overlay:#fff;--nuvra-shadow:0 0 12px #0000001f;--nuvra-fullscreen-z-index:2000}:where(.dark .document-editor,[data-theme=dark] .document-editor){--nuvra-color-primary-hover:#66b1ff;--nuvra-color-primary-border:#2a598a;--nuvra-color-primary-muted:#213d5b;--nuvra-color-primary-soft:#18222c;--nuvra-color-danger-soft:#2b1d1d;--nuvra-text-strong:#e5eaf3;--nuvra-text:#cfd3dc;--nuvra-text-muted:#a3a6ad;--nuvra-text-placeholder:#8d9095;--nuvra-text-disabled:#6c6e72;--nuvra-border:#4c4d4f;--nuvra-border-hover:#6c6e72;--nuvra-border-light:#414243;--nuvra-border-lighter:#363637;--nuvra-fill:#262727;--nuvra-bg:#141414;--nuvra-bg-overlay:#1d1e1f;--nuvra-shadow:0 0 12px #000000b8}.doc-content.is-format-painter{cursor:copy}.doc-content.doc-show-marks p:after,.doc-content.doc-show-marks h1:after,.doc-content.doc-show-marks h2:after,.doc-content.doc-show-marks h3:after,.doc-content.doc-show-marks h4:after,.doc-content.doc-show-marks h5:after,.doc-content.doc-show-marks h6:after{content:"¶";color:var(--nuvra-color-primary);opacity:.55;pointer-events:none;-webkit-user-select:none;user-select:none;margin-left:1px;font-family:system-ui,sans-serif;font-weight:400}.doc-tb-button{box-sizing:border-box;min-width:28px;height:28px;color:var(--nuvra-text);font:inherit;white-space:nowrap;cursor:pointer;background:0 0;border:0;border-radius:6px;flex:none;justify-content:center;align-items:center;gap:4px;padding:0 5px;font-size:13px;line-height:1;transition:background-color .12s,color .12s;display:inline-flex}.doc-tb-button:hover:not(:disabled){background:var(--nuvra-fill)}.doc-tb-button:focus-visible{outline:2px solid var(--nuvra-color-primary);outline-offset:-2px}.doc-tb-button.is-active{color:var(--nuvra-color-primary);background:var(--nuvra-color-primary-soft)}.doc-tb-button:disabled{color:var(--nuvra-text-disabled);cursor:not-allowed}.doc-tb-button--select{justify-content:space-between;padding:0 4px 0 7px}.doc-tb-button--caret{min-width:16px;padding:0 2px}.doc-tb-button__label{text-overflow:ellipsis;overflow:hidden}.doc-menu{--doc-popover-padding:4px}.doc-menu__items{min-width:168px;display:grid}.doc-menu__item{box-sizing:border-box;width:100%;color:var(--nuvra-text);font:inherit;text-align:left;white-space:nowrap;cursor:pointer;background:0 0;border:0;border-radius:6px;outline:none;align-items:center;gap:8px;padding:5px 12px 5px 8px;font-size:13px;line-height:20px;display:flex}.doc-menu__item:hover,.doc-menu__item:focus-visible{color:var(--nuvra-color-primary);background:var(--nuvra-color-primary-soft)}.doc-menu__item.is-selected{color:var(--nuvra-color-primary);font-weight:600}.doc-menu__item.is-danger:hover,.doc-menu__item.is-danger:focus-visible{color:var(--nuvra-color-danger);background:var(--nuvra-color-danger-soft)}.doc-menu__item:disabled{color:var(--nuvra-text-disabled);cursor:default;background:0 0}.doc-menu__divider{background:var(--nuvra-border-lighter);height:1px;margin:4px 0}.doc-menu__hint{color:var(--nuvra-text-placeholder);margin-left:auto;padding-left:20px;font-size:11px;font-weight:400}.doc-menu__h1{font-size:18px;font-weight:700}.doc-menu__h2{font-size:16px;font-weight:700}.doc-menu__h3{font-size:15px;font-weight:700}.doc-menu__h4{font-size:14px;font-weight:700}.doc-input{box-sizing:border-box;border:1px solid var(--nuvra-border);width:100%;min-width:0;height:24px;color:var(--nuvra-text);background:var(--nuvra-bg);font:inherit;border-radius:4px;outline:none;margin:0;padding:0 7px;font-size:12px;transition:border-color .12s}.doc-input::placeholder{color:var(--nuvra-text-placeholder)}.doc-input:hover{border-color:var(--nuvra-border-hover)}.doc-input:focus,.doc-input:focus-within{border-color:var(--nuvra-color-primary)}.doc-input--affix{align-items:center;gap:6px;display:inline-flex}.doc-input--affix input{min-width:0;height:100%;color:inherit;font:inherit;background:0 0;border:0;outline:none;flex:auto;margin:0;padding:0}.doc-input--affix input::placeholder{color:var(--nuvra-text-placeholder)}.doc-btn{box-sizing:border-box;border:1px solid var(--nuvra-border);height:24px;color:var(--nuvra-text);background:var(--nuvra-bg);font:inherit;white-space:nowrap;cursor:pointer;border-radius:4px;flex:none;justify-content:center;align-items:center;gap:5px;margin:0;padding:0 11px;font-size:12px;line-height:1;transition:background-color .12s,border-color .12s,color .12s;display:inline-flex}.doc-btn:hover:not(:disabled){border-color:var(--nuvra-color-primary-muted);color:var(--nuvra-color-primary);background:var(--nuvra-color-primary-soft)}.doc-btn:focus-visible{outline:2px solid var(--nuvra-color-primary-border);outline-offset:1px}.doc-btn:disabled{border-color:var(--nuvra-border-lighter);color:var(--nuvra-text-placeholder);cursor:not-allowed}.doc-btn--primary{border-color:var(--nuvra-color-primary);color:var(--nuvra-color-on-primary);background:var(--nuvra-color-primary)}.doc-btn--primary:hover:not(:disabled){border-color:var(--nuvra-color-primary-hover);color:var(--nuvra-color-on-primary);background:var(--nuvra-color-primary-hover)}.doc-btn--primary:disabled{border-color:var(--nuvra-color-primary-border);color:var(--nuvra-color-on-primary);background:var(--nuvra-color-primary-border)}.doc-btn--danger-text{color:var(--nuvra-color-danger);background:0 0;border-color:#0000}.doc-btn--danger-text:hover:not(:disabled){color:var(--nuvra-color-danger);background:var(--nuvra-color-danger-soft);border-color:#0000}.doc-checkbox{color:var(--nuvra-text);cursor:pointer;-webkit-user-select:none;user-select:none;align-items:center;gap:6px;font-size:12px;display:inline-flex}.doc-checkbox input{width:13px;height:13px;accent-color:var(--nuvra-color-primary);cursor:pointer;margin:0}.doc-spin{animation:1s linear infinite doc-spin}@keyframes doc-spin{to{transform:rotate(360deg)}}.doc-canvas .doc-content{--doc-placeholder:""}.doc-canvas .doc-content.is-empty>p:first-child:before{float:left;color:#98a2b3;content:var(--doc-placeholder);pointer-events:none;height:0}.doc-canvas .doc-content .doc-page-break{cursor:default;-webkit-user-select:none;user-select:none;height:18px;margin-bottom:6pt;position:relative}.doc-canvas .doc-content .doc-page-break:before{content:"";border-top:1px dashed #98a2b3;position:absolute;top:50%;left:0;right:0}.doc-canvas .doc-content .doc-page-break:after{color:#667085;letter-spacing:.04em;text-transform:uppercase;content:var(--page-break-label);background:#fff;padding:0 8px;font:10px/16px system-ui,sans-serif;position:absolute;top:50%;left:50%;transform:translate(-50%,-50%)}.doc-canvas .doc-content td,.doc-canvas .doc-content th{position:relative}.doc-canvas .doc-content .doc-cell-selected:after{content:"";pointer-events:none;background:#3b82f629;position:absolute;inset:0}.doc-canvas .doc-content.has-cell-selection ::selection{background:0 0}.doc-canvas .doc-content.is-column-resize,.doc-canvas .doc-content.is-column-resize *{cursor:col-resize}.doc-canvas .doc-content ul[data-type=taskList] input[type=checkbox]{cursor:pointer}.doc-canvas .doc-content a{cursor:text}::highlight(doc-search){background-color:#facc1573}::highlight(doc-search-current){background-color:#f973168c}.document-editor[data-v-0bbfea16]{--doc-editor-canvas-padding:50px;--doc-editor-height:760px;--doc-editor-min-height:240px;--doc-editor-max-height:600px;box-sizing:border-box;width:100%;min-width:0;height:var(--doc-editor-height);border:1px solid var(--nuvra-border);background:var(--nuvra-bg);border-radius:10px;flex-direction:column;min-height:360px;transition:border-color .16s;display:flex;position:relative;overflow:hidden;container-type:inline-size}.document-editor[data-v-0bbfea16]:focus-within{border-color:var(--nuvra-color-primary-border)}.document-editor.is-auto-height[data-v-0bbfea16]{height:auto;min-height:0}.document-editor.is-fullscreen[data-v-0bbfea16]{z-index:var(--nuvra-fullscreen-z-index);border:0;border-radius:0;height:100dvh;position:fixed;inset:0}.document-editor__body[data-v-0bbfea16]{flex-direction:column;flex:auto;min-height:0;display:flex;position:relative}.document-editor__source[data-v-0bbfea16]{box-sizing:border-box;color:#1f2328;resize:none;tab-size:2;background:#fbfcfd;border:0;outline:none;flex:auto;min-height:0;margin:0;padding:16px 20px;font:13px/1.6 ui-monospace,SFMono-Regular,Consolas,monospace}.document-editor__uploading[data-v-0bbfea16]{color:#fff;pointer-events:none;background:#101828cc;border-radius:999px;padding:6px 12px;font-size:12px;position:absolute;bottom:12px;left:50%;transform:translate(-50%)}
2
2
  /*$vite$:1*/
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nuvra",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "Word-style document editor for Vue 3: page view, tables, images, find & replace, print and Word export.",
5
5
  "keywords": [
6
6
  "vue",
@@ -14,7 +14,7 @@
14
14
  ],
15
15
  "license": "MIT",
16
16
  "author": "Eshonqul",
17
- "homepage": "https://github.com/eshonqul6772/nuvra#readme",
17
+ "homepage": "https://nuvra-docs.vercel.app",
18
18
  "repository": {
19
19
  "type": "git",
20
20
  "url": "git+https://github.com/eshonqul6772/nuvra.git"
@@ -1,59 +0,0 @@
1
- import { n as e } from "./page-CEEleKNI.js";
2
- //#region src/styles/document-content.css?inline
3
- var t = ".doc-content{color:#1f2328;white-space:pre-wrap;overflow-wrap:break-word;tab-size:4;font-family:Times New Roman,Times,serif;font-size:12pt;line-height:1.5}.doc-content :is(p,h1,h2,h3,h4,h5,h6):not([dir]){unicode-bidi:plaintext}.doc-content p{margin:0 0 6pt}.doc-content h1,.doc-content h2,.doc-content h3,.doc-content h4,.doc-content h5,.doc-content h6{margin:0 0 6pt;padding-top:6pt;font-weight:700;line-height:1.25}.doc-content h1{font-size:20pt}.doc-content h2{font-size:16pt}.doc-content h3{font-size:14pt}.doc-content h4{font-size:12pt}.doc-content h5{font-size:11pt}.doc-content h6{font-size:10pt}.doc-content ul,.doc-content ol{margin:0 0 6pt;padding-left:24pt}.doc-content li>p{margin-bottom:2pt}.doc-content ul[data-type=taskList]{padding-left:2pt;list-style:none}.doc-content ul[data-type=taskList] li{align-items:flex-start;gap:6pt;display:flex}.doc-content ul[data-type=taskList] li>label{-webkit-user-select:none;user-select:none;flex:none;margin-top:.3em}.doc-content ul[data-type=taskList] li>div{flex:auto;min-width:0}.doc-content ul[data-type=taskList] li[data-checked=true]>div{color:#667085;text-decoration:line-through}.doc-content blockquote{color:#475467;border-left:3px solid #b3c5f5;margin:0 0 6pt;padding:2pt 0 2pt 12pt}.doc-content blockquote>p:last-child,.doc-content li>p:last-child,.doc-content td>p:last-child,.doc-content th>p:last-child{margin-bottom:0}.doc-content pre{white-space:pre-wrap;background:#f4f6f8;border-radius:4px;margin:0 0 6pt;padding:8pt 10pt;font-family:Consolas,Courier New,monospace;font-size:10pt;line-height:1.45}.doc-content code{background:#eef1f4;border-radius:3px;padding:1px 4px;font-family:Consolas,Courier New,monospace;font-size:.9em}.doc-content pre code{font-size:inherit;background:0 0;padding:0}.doc-content hr{border:0;border-bottom:1px solid #c4cad4;height:0;margin:0 0 6pt;padding-top:6pt}.doc-content a{color:#1d4ed8;text-decoration:underline}.doc-content mark{color:inherit;border-radius:2px;padding:0 1px}.doc-content img{max-width:100%;height:auto}.doc-content img[data-align=left]{margin:0 auto 6pt 0;display:block}.doc-content img[data-align=center]{margin:0 auto 6pt;display:block}.doc-content img[data-align=right]{margin:0 0 6pt auto;display:block}.doc-content table{border-collapse:collapse;table-layout:fixed;width:100%;margin:0 0 6pt}.doc-content td,.doc-content th{box-sizing:border-box;vertical-align:top;border:1px solid #8f99a8;min-width:1em;padding:3pt 5pt}.doc-content th{text-align:left;background:#f2f4f7;font-weight:700}.doc-content .doc-page-break{break-after:page;page-break-after:always;height:0}", n = "", r = {
4
- "&": "&amp;",
5
- "<": "&lt;",
6
- ">": "&gt;",
7
- "\"": "&quot;",
8
- "'": "&#39;"
9
- }, i = /<div[^>]*data-type="page-break"[^>]*><\/div>/g, a = "<br clear=\"all\" style=\"page-break-before: always\">", o = /[\\/:*?"<>|]+/g, s = "document", c = 6e4, l = {
10
- position: "fixed",
11
- left: "-10000px",
12
- top: "0",
13
- width: "1px",
14
- height: "1px",
15
- border: "0"
16
- }, u = (e) => e.replace(/[&<>"']/g, (e) => r[e] ?? e), d = ({ size: t, orientation: n, margins: r }) => {
17
- let i = e[t] ?? e.a4, [a, o] = n === "portrait" ? [i.width, i.height] : [i.height, i.width];
18
- return `size: ${a}mm ${o}mm; margin: ${r.top}mm ${r.right}mm ${r.bottom}mm ${r.left}mm;`;
19
- }, f = (e) => e.replace(o, " ").trim() || s, p = ({ html: e, title: n, page: r }) => `<!doctype html>
20
- <html lang="uz">
21
- <head>
22
- <meta charset="utf-8">
23
- <title>${u(n)}</title>
24
- <style>@page { ${d(r)} } html, body { margin: 0; background: #fff; } ${t}</style>
25
- </head>
26
- <body><article class="doc-content">${e}</article></body>
27
- </html>`, m = ({ html: e, title: r, page: o }) => {
28
- let s = e.replace(i, a);
29
- return `${n}<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns="http://www.w3.org/TR/REC-html40">
30
- <head>
31
- <meta charset="utf-8">
32
- <title>${u(r)}</title>
33
- <!--[if gte mso 9]><xml><w:WordDocument><w:View>Print</w:View><w:Zoom>100</w:Zoom></w:WordDocument></xml><![endif]-->
34
- <style>@page Section1 { ${d(o)} } div.Section1 { page: Section1; } ${t}</style>
35
- </head>
36
- <body><div class="Section1 doc-content">${s}</div></body>
37
- </html>`;
38
- }, h = (e, t, n) => {
39
- let r = URL.createObjectURL(new Blob([e], { type: n })), i = document.createElement("a");
40
- i.href = r, i.download = t, i.click(), setTimeout(() => URL.revokeObjectURL(r), 0);
41
- }, g = (e) => {
42
- let t = document.createElement("iframe");
43
- t.setAttribute("aria-hidden", "true"), t.tabIndex = -1, Object.assign(t.style, l);
44
- let n = () => t.remove();
45
- t.onload = () => {
46
- let e = t.contentWindow;
47
- if (!e) return n();
48
- let r = Array.from(e.document.images).filter((e) => !e.complete).map((e) => new Promise((t) => {
49
- e.addEventListener("load", t, { once: !0 }), e.addEventListener("error", t, { once: !0 });
50
- }));
51
- Promise.allSettled(r).then(() => {
52
- e.addEventListener("afterprint", () => setTimeout(n, 0), { once: !0 }), e.focus(), e.print(), setTimeout(n, c);
53
- });
54
- }, t.srcdoc = e, document.body.appendChild(t);
55
- };
56
- //#endregion
57
- export { p as buildPrintableHtml, m as buildWordHtml, h as downloadFile, g as printHtml, f as toFileName };
58
-
59
- //# sourceMappingURL=export-cyOnlakM.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"export-cyOnlakM.js","names":[],"sources":["../src/styles/document-content.css?inline","../src/core/export.ts"],"sourcesContent":["/*\n * Typography of the document itself. Shared by the editor page, print output and Word/HTML export,\n * so every rule is plain CSS scoped to `.doc-content`. Vertical rhythm uses bottom margins only:\n * no margin collapsing keeps page layout measurements exact.\n */\n\n/* Base text. Typed spaces are content, so they are kept exactly. */\n.doc-content {\n color: #1f2328;\n font-family: \"Times New Roman\", Times, serif;\n font-size: 12pt;\n line-height: 1.5;\n white-space: pre-wrap;\n overflow-wrap: break-word;\n tab-size: 4;\n}\n\n/* Paragraphs without an explicit direction follow their own text (Arabic and Latin in one document). */\n.doc-content :is(p, h1, h2, h3, h4, h5, h6):not([dir]) {\n unicode-bidi: plaintext;\n}\n\n/* Paragraphs and headings. */\n.doc-content p {\n margin: 0 0 6pt;\n}\n\n.doc-content h1,\n.doc-content h2,\n.doc-content h3,\n.doc-content h4,\n.doc-content h5,\n.doc-content h6 {\n margin: 0 0 6pt;\n padding-top: 6pt;\n font-weight: 700;\n line-height: 1.25;\n}\n\n.doc-content h1 {\n font-size: 20pt;\n}\n\n.doc-content h2 {\n font-size: 16pt;\n}\n\n.doc-content h3 {\n font-size: 14pt;\n}\n\n.doc-content h4 {\n font-size: 12pt;\n}\n\n.doc-content h5 {\n font-size: 11pt;\n}\n\n.doc-content h6 {\n font-size: 10pt;\n}\n\n/* Lists, including task lists with a checkbox label and a content column. */\n.doc-content ul,\n.doc-content ol {\n margin: 0 0 6pt;\n padding-left: 24pt;\n}\n\n.doc-content li > p {\n margin-bottom: 2pt;\n}\n\n.doc-content ul[data-type=\"taskList\"] {\n padding-left: 2pt;\n list-style: none;\n}\n\n.doc-content ul[data-type=\"taskList\"] li {\n display: flex;\n align-items: flex-start;\n gap: 6pt;\n}\n\n.doc-content ul[data-type=\"taskList\"] li > label {\n flex: 0 0 auto;\n margin-top: 0.3em;\n user-select: none;\n}\n\n.doc-content ul[data-type=\"taskList\"] li > div {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.doc-content ul[data-type=\"taskList\"] li[data-checked=\"true\"] > div {\n color: #667085;\n text-decoration: line-through;\n}\n\n/* Quotes. */\n.doc-content blockquote {\n margin: 0 0 6pt;\n padding: 2pt 0 2pt 12pt;\n border-left: 3px solid #b3c5f5;\n color: #475467;\n}\n\n/* The last paragraph of a container adds no space below it. */\n.doc-content blockquote > p:last-child,\n.doc-content li > p:last-child,\n.doc-content td > p:last-child,\n.doc-content th > p:last-child {\n margin-bottom: 0;\n}\n\n/* Code blocks and inline code. */\n.doc-content pre {\n margin: 0 0 6pt;\n padding: 8pt 10pt;\n border-radius: 4px;\n background: #f4f6f8;\n font-family: Consolas, \"Courier New\", monospace;\n font-size: 10pt;\n line-height: 1.45;\n white-space: pre-wrap;\n}\n\n.doc-content code {\n padding: 1px 4px;\n border-radius: 3px;\n background: #eef1f4;\n font-family: Consolas, \"Courier New\", monospace;\n font-size: 0.9em;\n}\n\n.doc-content pre code {\n padding: 0;\n background: none;\n font-size: inherit;\n}\n\n/* Horizontal rule. */\n.doc-content hr {\n height: 0;\n margin: 0 0 6pt;\n padding-top: 6pt;\n border: 0;\n border-bottom: 1px solid #c4cad4;\n}\n\n/* Inline marks. */\n.doc-content a {\n color: #1d4ed8;\n text-decoration: underline;\n}\n\n.doc-content mark {\n padding: 0 1px;\n border-radius: 2px;\n color: inherit;\n}\n\n/* Images are blocks aligned through their data-align attribute. */\n.doc-content img {\n max-width: 100%;\n height: auto;\n}\n\n.doc-content img[data-align=\"left\"] {\n display: block;\n margin: 0 auto 6pt 0;\n}\n\n.doc-content img[data-align=\"center\"] {\n display: block;\n margin: 0 auto 6pt;\n}\n\n.doc-content img[data-align=\"right\"] {\n display: block;\n margin: 0 0 6pt auto;\n}\n\n/* Tables. */\n.doc-content table {\n width: 100%;\n margin: 0 0 6pt;\n border-collapse: collapse;\n table-layout: fixed;\n}\n\n.doc-content td,\n.doc-content th {\n box-sizing: border-box;\n min-width: 1em;\n padding: 3pt 5pt;\n border: 1px solid #8f99a8;\n vertical-align: top;\n}\n\n.doc-content th {\n background: #f2f4f7;\n font-weight: 700;\n text-align: left;\n}\n\n/* Manual page break: invisible in print, where it starts a new sheet. */\n.doc-content .doc-page-break {\n height: 0;\n break-after: page;\n page-break-after: always;\n}\n","import contentCss from '../styles/document-content.css?inline';\nimport { PAGE_SIZES, type PageSettings } from './page';\n\n/** Everything needed to print or export the document. */\ninterface DocumentSnapshot {\n /** Clean document HTML. */\n html: string;\n /** Document title, used for the print title and file names. */\n title: string;\n /** Page size, orientation and margins. */\n page: PageSettings;\n}\n\n/** Makes Word detect UTF-8 instead of the system code page. */\nconst BYTE_ORDER_MARK = String.fromCharCode(0xfe_ff);\n/** Characters escaped when text is placed into HTML. */\nconst HTML_ESCAPES: Record<string, string> = { '&': '&amp;', '<': '&lt;', '>': '&gt;', '\"': '&quot;', \"'\": '&#39;' };\n/** Page break markup of the editor. */\nconst PAGE_BREAK_PATTERN = /<div[^>]*data-type=\"page-break\"[^>]*><\\/div>/g;\n/** Page break markup Word understands. */\nconst WORD_PAGE_BREAK = '<br clear=\"all\" style=\"page-break-before: always\">';\n/** Characters not allowed in file names on common systems. */\nconst INVALID_FILE_NAME_CHARACTERS = /[\\\\/:*?\"<>|]+/g;\n/** File name used when the title is empty. */\nconst DEFAULT_FILE_NAME = 'document';\n/** Removes the print iframe even when the browser never reports `afterprint`. */\nconst PRINT_CLEANUP_TIMEOUT_MS = 60_000;\n/** Styles that keep the print iframe out of view without `display: none`, which would stop it from printing. */\nconst HIDDEN_FRAME_STYLE: Partial<CSSStyleDeclaration> = {\n position: 'fixed',\n left: '-10000px',\n top: '0',\n width: '1px',\n height: '1px',\n border: '0'\n};\n\n/** Escapes text for use inside HTML. */\nconst escapeHtml = (value: string) => value.replace(/[&<>\"']/g, character => HTML_ESCAPES[character] ?? character);\n\n/** CSS declarations for `@page` with the paper size and margins of the page settings. */\nconst pageRule = ({ size, orientation, margins }: PageSettings) => {\n const paper = PAGE_SIZES[size] ?? PAGE_SIZES.a4;\n const [width, height] = orientation === 'portrait' ? [paper.width, paper.height] : [paper.height, paper.width];\n return `size: ${width}mm ${height}mm; margin: ${margins.top}mm ${margins.right}mm ${margins.bottom}mm ${margins.left}mm;`;\n};\n\n/** Turns a document title into a safe file name without extension. */\nexport const toFileName = (title: string): string =>\n title.replace(INVALID_FILE_NAME_CHARACTERS, ' ').trim() || DEFAULT_FILE_NAME;\n\n/** Standalone HTML with the page size and margins encoded as `@page`, used for printing and HTML export. */\nexport const buildPrintableHtml = ({ html, title, page }: DocumentSnapshot): string =>\n `<!doctype html>\n<html lang=\"uz\">\n<head>\n<meta charset=\"utf-8\">\n<title>${escapeHtml(title)}</title>\n<style>@page { ${pageRule(page)} } html, body { margin: 0; background: #fff; } ${contentCss}</style>\n</head>\n<body><article class=\"doc-content\">${html}</article></body>\n</html>`;\n\n/** Word opens HTML saved with the Office namespaces as a regular document in print layout. */\nexport const buildWordHtml = ({ html, title, page }: DocumentSnapshot): string => {\n const body = html.replace(PAGE_BREAK_PATTERN, WORD_PAGE_BREAK);\n return `${BYTE_ORDER_MARK}<html xmlns:o=\"urn:schemas-microsoft-com:office:office\" xmlns:w=\"urn:schemas-microsoft-com:office:word\" xmlns=\"http://www.w3.org/TR/REC-html40\">\n<head>\n<meta charset=\"utf-8\">\n<title>${escapeHtml(title)}</title>\n<!--[if gte mso 9]><xml><w:WordDocument><w:View>Print</w:View><w:Zoom>100</w:Zoom></w:WordDocument></xml><![endif]-->\n<style>@page Section1 { ${pageRule(page)} } div.Section1 { page: Section1; } ${contentCss}</style>\n</head>\n<body><div class=\"Section1 doc-content\">${body}</div></body>\n</html>`;\n};\n\n/** Offers text content as a file download. */\nexport const downloadFile = (content: string, fileName: string, type: string): void => {\n const url = URL.createObjectURL(new Blob([content], { type }));\n const link = document.createElement('a');\n link.href = url;\n link.download = fileName;\n link.click();\n setTimeout(() => URL.revokeObjectURL(url), 0);\n};\n\n/** Prints through a detached iframe so the application chrome never ends up on paper. Waits for images first. */\nexport const printHtml = (documentHtml: string): void => {\n const frame = document.createElement('iframe');\n frame.setAttribute('aria-hidden', 'true');\n frame.tabIndex = -1;\n Object.assign(frame.style, HIDDEN_FRAME_STYLE);\n\n /** Removes the iframe once printing is done. */\n const cleanup = () => frame.remove();\n frame.onload = () => {\n const printWindow = frame.contentWindow;\n if (!printWindow) return cleanup();\n const pendingImages = Array.from(printWindow.document.images)\n .filter(image => !image.complete)\n .map(\n image =>\n new Promise(resolve => {\n image.addEventListener('load', resolve, { once: true });\n image.addEventListener('error', resolve, { once: true });\n })\n );\n void Promise.allSettled(pendingImages).then(() => {\n printWindow.addEventListener('afterprint', () => setTimeout(cleanup, 0), { once: true });\n printWindow.focus();\n printWindow.print();\n setTimeout(cleanup, PRINT_CLEANUP_TIMEOUT_MS);\n });\n };\n frame.srcdoc = documentHtml;\n document.body.appendChild(frame);\n};\n"],"mappings":";;yiFCcM,IAAkB,KAElB,IAAuC;CAAE,KAAK;CAAS,KAAK;CAAQ,KAAK;CAAQ,MAAK;CAAU,KAAK;AAAQ,GAE7G,IAAqB,iDAErB,IAAkB,0DAElB,IAA+B,kBAE/B,IAAoB,YAEpB,IAA2B,KAE3B,IAAmD;CACvD,UAAU;CACV,MAAM;CACN,KAAK;CACL,OAAO;CACP,QAAQ;CACR,QAAQ;AACV,GAGM,KAAc,MAAkB,EAAM,QAAQ,aAAY,MAAa,EAAa,MAAc,CAAS,GAG3G,KAAY,EAAE,SAAM,gBAAa,iBAA4B;CACjE,IAAM,IAAQ,EAAW,MAAS,EAAW,IACvC,CAAC,GAAO,KAAU,MAAgB,aAAa,CAAC,EAAM,OAAO,EAAM,MAAM,IAAI,CAAC,EAAM,QAAQ,EAAM,KAAK;CAC7G,OAAO,SAAS,EAAM,KAAK,EAAO,cAAc,EAAQ,IAAI,KAAK,EAAQ,MAAM,KAAK,EAAQ,OAAO,KAAK,EAAQ,KAAK;AACvH,GAGa,KAAc,MACzB,EAAM,QAAQ,GAA8B,GAAG,CAAC,CAAC,KAAK,KAAK,GAGhD,KAAsB,EAAE,SAAM,UAAO,cAChD;;;;SAIO,EAAW,CAAK,EAAE;iBACV,EAAS,CAAI,EAAE,iDAAiD,EAAW;;qCAEvD,EAAK;UAI7B,KAAiB,EAAE,SAAM,UAAO,cAAqC;CAChF,IAAM,IAAO,EAAK,QAAQ,GAAoB,CAAe;CAC7D,OAAO,GAAG,EAAgB;;;SAGnB,EAAW,CAAK,EAAE;;0BAED,EAAS,CAAI,EAAE,sCAAsC,EAAW;;0CAEhD,EAAK;;AAE/C,GAGa,KAAgB,GAAiB,GAAkB,MAAuB;CACrF,IAAM,IAAM,IAAI,gBAAgB,IAAI,KAAK,CAAC,CAAO,GAAG,EAAE,QAAK,CAAC,CAAC,GACvD,IAAO,SAAS,cAAc,GAAG;CAIvC,AAHA,EAAK,OAAO,GACZ,EAAK,WAAW,GAChB,EAAK,MAAM,GACX,iBAAiB,IAAI,gBAAgB,CAAG,GAAG,CAAC;AAC9C,GAGa,KAAa,MAA+B;CACvD,IAAM,IAAQ,SAAS,cAAc,QAAQ;CAG7C,AAFA,EAAM,aAAa,eAAe,MAAM,GACxC,EAAM,WAAW,IACjB,OAAO,OAAO,EAAM,OAAO,CAAkB;CAG7C,IAAM,UAAgB,EAAM,OAAO;CAqBnC,AApBA,EAAM,eAAe;EACnB,IAAM,IAAc,EAAM;EAC1B,IAAI,CAAC,GAAa,OAAO,EAAQ;EACjC,IAAM,IAAgB,MAAM,KAAK,EAAY,SAAS,MAAM,CAAC,CAC1D,QAAO,MAAS,CAAC,EAAM,QAAQ,CAAC,CAChC,KACC,MACE,IAAI,SAAQ,MAAW;GAErB,AADA,EAAM,iBAAiB,QAAQ,GAAS,EAAE,MAAM,GAAK,CAAC,GACtD,EAAM,iBAAiB,SAAS,GAAS,EAAE,MAAM,GAAK,CAAC;EACzD,CAAC,CACL;EACF,QAAa,WAAW,CAAa,CAAC,CAAC,WAAW;GAIhD,AAHA,EAAY,iBAAiB,oBAAoB,WAAW,GAAS,CAAC,GAAG,EAAE,MAAM,GAAK,CAAC,GACvF,EAAY,MAAM,GAClB,EAAY,MAAM,GAClB,WAAW,GAAS,CAAwB;EAC9C,CAAC;CACH,GACA,EAAM,SAAS,GACf,SAAS,KAAK,YAAY,CAAK;AACjC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"page-CEEleKNI.js","names":[],"sources":["../src/core/page.ts"],"sourcesContent":["/** Supported paper formats. */\nexport type PageSizeKey = 'a3' | 'a4' | 'a5' | 'letter' | 'legal';\n/** Paper orientation. */\nexport type PageOrientation = 'portrait' | 'landscape';\n/** `page` shows sheets like a word processor, `web` a continuous surface. */\nexport type DocumentViewMode = 'page' | 'web';\n\n/** Page margins in millimetres. */\nexport interface PageMargins {\n /** Top margin. */\n top: number;\n /** Right margin. */\n right: number;\n /** Bottom margin. */\n bottom: number;\n /** Left margin. */\n left: number;\n}\n\n/** Page setup chosen by the user; the host can persist it with `v-model:page`. */\nexport interface PageSettings {\n /** Paper format. */\n size: PageSizeKey;\n /** Paper orientation. */\n orientation: PageOrientation;\n /** Margins in millimetres. */\n margins: PageMargins;\n}\n\n/** Page geometry in CSS pixels, ready for layout. */\nexport interface PageMetrics {\n /** Sheet width. */\n width: number;\n /** Sheet height. */\n height: number;\n /** Grey space between two sheets. */\n gap: number;\n /** Top margin. */\n marginTop: number;\n /** Right margin. */\n marginRight: number;\n /** Bottom margin. */\n marginBottom: number;\n /** Left margin. */\n marginLeft: number;\n}\n\n/** Portrait dimensions of a paper format in millimetres. */\ninterface PaperSize {\n /** Name shown in the page setup. */\n label: string;\n /** Portrait width. */\n width: number;\n /** Portrait height. */\n height: number;\n}\n\n/** Paper sizes in millimetres (portrait). */\nexport const PAGE_SIZES: Record<PageSizeKey, PaperSize> = {\n a3: { label: 'A3', width: 297, height: 420 },\n a4: { label: 'A4', width: 210, height: 297 },\n a5: { label: 'A5', width: 148, height: 210 },\n letter: { label: 'Letter', width: 215.9, height: 279.4 },\n legal: { label: 'Legal', width: 215.9, height: 355.6 }\n};\n\n/** Margin presets offered by the page setup, in millimetres; the key doubles as the label suffix. */\nexport const MARGIN_PRESETS = [\n { key: 'normal', margins: { top: 25.4, right: 25.4, bottom: 25.4, left: 25.4 } },\n { key: 'narrow', margins: { top: 12.7, right: 12.7, bottom: 12.7, left: 12.7 } },\n { key: 'moderate', margins: { top: 25.4, right: 19.1, bottom: 25.4, left: 19.1 } },\n { key: 'wide', margins: { top: 25.4, right: 50.8, bottom: 25.4, left: 50.8 } },\n /** O‘zDSt 1.14 requisites for official documents. */\n { key: 'official', margins: { top: 20, right: 15, bottom: 20, left: 30 } }\n] as const satisfies ReadonlyArray<{ key: string; margins: PageMargins }>;\n\n/** Smallest zoom in percent; low enough for an A4 sheet to fit a phone screen. */\nexport const ZOOM_MIN = 30;\n/** Largest zoom in percent. */\nexport const ZOOM_MAX = 200;\n/** Zoom change per step of the zoom buttons and slider, in percent. */\nexport const ZOOM_STEP = 10;\n\n/** Grey space between two sheets in page view, in CSS pixels. */\nconst PAGE_GAP = 20;\n/** CSS pixels per millimetre at 96 DPI. */\nconst PX_PER_MM = 96 / 25.4;\n/** Margin differences below this many millimetres count as equal (rounding of unit conversions). */\nconst MARGIN_TOLERANCE_MM = 0.05;\n\n/** Converts millimetres to CSS pixels. */\nconst mmToPx = (value: number): number => value * PX_PER_MM;\n\n/** Default page setup: portrait A4 with normal margins. */\nexport const createPageSettings = (): PageSettings => ({\n size: 'a4',\n orientation: 'portrait',\n margins: { ...MARGIN_PRESETS[0].margins }\n});\n\n/** Converts page settings into pixel geometry; an unknown paper size falls back to A4. */\nexport const getPageMetrics = ({ size, orientation, margins }: PageSettings): PageMetrics => {\n const paper = PAGE_SIZES[size] ?? PAGE_SIZES.a4;\n const portrait = orientation === 'portrait';\n return {\n width: mmToPx(portrait ? paper.width : paper.height),\n height: mmToPx(portrait ? paper.height : paper.width),\n gap: PAGE_GAP,\n marginTop: mmToPx(margins.top),\n marginRight: mmToPx(margins.right),\n marginBottom: mmToPx(margins.bottom),\n marginLeft: mmToPx(margins.left)\n };\n};\n\n/** Whether two margin sets are equal, used to highlight the matching preset. */\nexport const isSameMargins = (a: PageMargins, b: PageMargins): boolean =>\n (Object.keys(a) as Array<keyof PageMargins>).every(side => Math.abs(a[side] - b[side]) < MARGIN_TOLERANCE_MM);\n"],"mappings":";AA0DA,IAAa,IAA6C;CACxD,IAAI;EAAE,OAAO;EAAM,OAAO;EAAK,QAAQ;CAAI;CAC3C,IAAI;EAAE,OAAO;EAAM,OAAO;EAAK,QAAQ;CAAI;CAC3C,IAAI;EAAE,OAAO;EAAM,OAAO;EAAK,QAAQ;CAAI;CAC3C,QAAQ;EAAE,OAAO;EAAU,OAAO;EAAO,QAAQ;CAAM;CACvD,OAAO;EAAE,OAAO;EAAS,OAAO;EAAO,QAAQ;CAAM;AACvD,GAGa,IAAiB;CAC5B;EAAE,KAAK;EAAU,SAAS;GAAE,KAAK;GAAM,OAAO;GAAM,QAAQ;GAAM,MAAM;EAAK;CAAE;CAC/E;EAAE,KAAK;EAAU,SAAS;GAAE,KAAK;GAAM,OAAO;GAAM,QAAQ;GAAM,MAAM;EAAK;CAAE;CAC/E;EAAE,KAAK;EAAY,SAAS;GAAE,KAAK;GAAM,OAAO;GAAM,QAAQ;GAAM,MAAM;EAAK;CAAE;CACjF;EAAE,KAAK;EAAQ,SAAS;GAAE,KAAK;GAAM,OAAO;GAAM,QAAQ;GAAM,MAAM;EAAK;CAAE;CAE7E;EAAE,KAAK;EAAY,SAAS;GAAE,KAAK;GAAI,OAAO;GAAI,QAAQ;GAAI,MAAM;EAAG;CAAE;AAC3E,GAUM,IAAW,IAEX,IAAY,KAAK,MAEjB,IAAsB,KAGtB,KAAU,MAA0B,IAAQ,GAGrC,WAA0C;CACrD,MAAM;CACN,aAAa;CACb,SAAS,EAAE,GAAG,EAAe,EAAE,CAAC,QAAQ;AAC1C,IAGa,KAAkB,EAAE,SAAM,gBAAa,iBAAyC;CAC3F,IAAM,IAAQ,EAAW,MAAS,EAAW,IACvC,IAAW,MAAgB;CACjC,OAAO;EACL,OAAO,EAAO,IAAW,EAAM,QAAQ,EAAM,MAAM;EACnD,QAAQ,EAAO,IAAW,EAAM,SAAS,EAAM,KAAK;EACpD,KAAK;EACL,WAAW,EAAO,EAAQ,GAAG;EAC7B,aAAa,EAAO,EAAQ,KAAK;EACjC,cAAc,EAAO,EAAQ,MAAM;EACnC,YAAY,EAAO,EAAQ,IAAI;CACjC;AACF,GAGa,KAAiB,GAAgB,MAC3C,OAAO,KAAK,CAAC,CAAC,CAA8B,OAAM,MAAQ,KAAK,IAAI,EAAE,KAAQ,EAAE,EAAK,IAAI,CAAmB"}