polotno 4.2.1 → 4.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.
- package/blueprint/pages-timeline/page-preview.js +2 -2
- package/blueprint/toolbar/html-toolbar.js +3 -3
- package/canvas/apply-filters.d.ts +11 -0
- package/canvas/apply-filters.js +1 -1
- package/canvas/audio.js +1 -1
- package/canvas/element.js +1 -1
- package/canvas/gif-element.js +1 -1
- package/canvas/hotkeys.d.ts +8 -0
- package/canvas/hotkeys.js +1 -1
- package/canvas/html-element.js +1 -1
- package/canvas/image-element.js +1 -1
- package/canvas/render-tag-element.js +1 -1
- package/canvas/rich-editor.js +2 -2
- package/canvas/table-element.js +1 -1
- package/canvas/text-element/fit-font-size.js +1 -1
- package/canvas/text-element.js +1 -1
- package/canvas/tooltip.js +1 -1
- package/canvas/use-filtered-source.d.ts +2 -0
- package/canvas/use-filtered-source.js +1 -0
- package/canvas/use-mediabunny-video.js +1 -1
- package/canvas/video-element.d.ts +1 -1
- package/canvas/video-element.js +1 -1
- package/canvas/workspace-canvas.d.ts +2 -1
- package/canvas/workspace-canvas.js +1 -1
- package/model/group-model.d.ts +1 -0
- package/model/group-model.js +1 -1
- package/model/page-model.d.ts +1 -0
- package/model/store.d.ts +9 -0
- package/model/store.js +1 -1
- package/model/text-model.d.ts +1 -0
- package/model/text-model.js +1 -1
- package/package.json +3 -3
- package/pages-timeline/page-preview.js +1 -1
- package/polotno.bundle.js +127 -126
- package/side-panel/effects-panel.js +1 -1
- package/side-panel/upload-panel.d.ts +1 -3
- package/side-panel/upload-panel.js +1 -1
- package/toolbar/html-toolbar.js +3 -3
- package/utils/base64.d.ts +2 -0
- package/utils/base64.js +1 -0
- package/utils/clipboard.d.ts +361 -0
- package/utils/clipboard.js +1 -1
- package/utils/errors.d.ts +7 -0
- package/utils/errors.js +1 -0
- package/utils/file.d.ts +6 -0
- package/utils/file.js +1 -1
- package/utils/fonts.js +1 -1
- package/utils/image-dpi.js +1 -1
- package/utils/insert-file.d.ts +23 -0
- package/utils/insert-file.js +1 -0
- package/utils/l10n.d.ts +4 -0
- package/utils/l10n.js +1 -1
- package/utils/loader.d.ts +3 -2
- package/utils/loader.js +1 -1
- package/utils/mobx.d.ts +4 -0
- package/utils/mobx.js +1 -0
- package/utils/text-html.d.ts +1 -0
- package/utils/text-html.js +1 -1
- package/utils/text-types.d.ts +2 -0
- package/utils/text-types.js +1 -1
- package/utils/to-html.js +1 -1
- package/utils/to-svg.js +1 -1
- package/utils/validate-key.js +1 -1
- package/utils/video.js +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as e,jsxs as a}from"react/jsx-runtime";import
|
|
1
|
+
import{jsx as e,jsxs as a}from"react/jsx-runtime";import o from"react";import{Slider as l}from"../primitives/slider.js";import{firstSliderValue as r}from"../lib/utils.js";import{SliderField as t}from"../primitives/slider-field.js";import{FieldGroup as n}from"../primitives/field-group.js";import{observer as i}from"mobx-react-lite";import{INDEPENDENT_FILTERS as s}from"../model/shape-model.js";import{ColorPicker as d}from"../toolbar/color-picker.js";import{t as b}from"../utils/l10n.js";import{EffectCard as h}from"./effect-card.js";import{Effects as c}from"../utils/filters.js";import{CurvePowerSlider as u}from"../toolbar/filters-picker.js";import{NumericInput as m}from"../primitives/numeric-input.js";import{FieldRow as g}from"../primitives/field-row.js";import{PanelHeader as p}from"../primitives/panel-header.js";import{ToggleGroup as f,ToggleGroupItem as v}from"../primitives/toggle-group.js";import{normalizeStrokeLineJoin as C}from"../utils/text-html.js";const x=[{value:"round",labelKey:"toolbar.joinRound"},{value:"miter",labelKey:"toolbar.joinMiter"},{value:"bevel",labelKey:"toolbar.joinBevel"}],y=({join:a})=>e("svg",{width:"22",height:"22",viewBox:"0 0 24 24",fill:"none","aria-hidden":"true",children:e("path",{d:"M7 21 L7 7 L21 7",stroke:"currentColor",strokeWidth:"9",strokeLinejoin:a,strokeLinecap:"butt"})});export{m as NumberInput};const k=(e,a,o)=>Math.max(a,Math.min(o,e)),w=[["temperature","toolbar.temperature"],["contrast","toolbar.contrast"],["shadows","toolbar.shadows"],["white","toolbar.white"],["black","toolbar.black"],["vibrance","toolbar.vibrance"],["saturation","toolbar.saturation"]],E=({store:o,color:t,onColorChange:n,value:i,onValueChange:s,min:b,max:h})=>a("div",{style:{display:"flex",alignItems:"center",padding:"8px 0"},children:[e(d,{value:t,size:30,gradientEnabled:!0,onChange:n,store:o}),e("div",{style:{flex:1,paddingLeft:"10px",paddingRight:"10px"},children:e(l,{value:[i],onValueChange:e=>s(k(r(e),b,h)),min:b,max:h,step:1})}),e(m,{value:i,onValueChange:e=>s(k(e,b,h)),min:b,max:h,style:{width:64}})]});export const EffectsPanel=i(({store:l})=>{const r=l.selectedElements,i=r[0],j=r.map(e=>e.id).join(","),M="effects"===l.openedSidePanel;if(o.useEffect(()=>{M&&(i&&i.filters||l.restoreSidePanel())},[M,j]),!i||!i.filters){return null}const S="text"===i.type,R="image"===i.type,P="svg"===i.type,z=R||P,L=e=>{l.history.transaction(()=>{r.forEach(a=>{a.set(e)})})},O=(e,a)=>{l.history.transaction(()=>{r.forEach(o=>{let l=Number(a);return 0==a||a||(l=o.filters.has(e)?null:1),s.includes(e)||o.set({grayscaleEnabled:"grayscale"===e&&!!a,sepiaEnabled:"sepia"===e&&!!a}),o.setFilter(e,l)})})};return a("div",{style:{height:"100%",display:"flex",flexDirection:"column",overflow:"auto",padding:"0 10px"},children:[e(p,{title:b("sidePanel.effects"),onClose:()=>l.restoreSidePanel()}),z&&e("div",{style:{display:"flex",flexDirection:"column",gap:"16px",marginTop:"16px"},children:a("div",{style:{display:"flex",gap:"16px",flexWrap:"wrap"},children:[e(h,{active:i.grayscaleEnabled,onClick:()=>{O("grayscale",!i.grayscaleEnabled)},title:b("toolbar.grayscale"),imageSrc:i.src,effect:c.grayscale}),e(h,{active:i.sepiaEnabled,onClick:()=>{O("sepia",!i.sepiaEnabled)},title:b("toolbar.sepia"),imageSrc:i.src,effect:c.sepia}),e(h,{active:i.filters.has("cold"),onClick:()=>{O("cold",i.filters.has("cold")?null:1)},title:b("toolbar.cold"),imageSrc:i.src,effect:c.cold}),e(h,{active:i.filters.has("natural"),onClick:()=>{O("natural",i.filters.has("natural")?null:1)},title:b("toolbar.natural"),imageSrc:i.src,effect:c.natural}),e(h,{active:i.filters.has("warm"),onClick:()=>{O("warm",i.filters.has("warm")?null:1)},title:b("toolbar.warm"),imageSrc:i.src,effect:c.warm})]})}),e(t,{label:b("toolbar.blur"),enabled:i.blurEnabled,visible:z||S,onEnabledChange:e=>{L({blurEnabled:e})},value:i.blurRadius,onChange:e=>{L({blurRadius:e})},min:0,max:100}),e(t,{label:b("toolbar.brightness"),visible:z,enabled:i.brightnessEnabled,onEnabledChange:e=>{L({brightnessEnabled:e})},value:Math.round(100*i.brightness),onChange:e=>{L({brightness:e/100})},min:-100,max:100}),w.map(([a,o])=>{var l,r;return e(t,{label:b(o),visible:z,enabled:i.filters.has(a),onEnabledChange:e=>{O(a,e?0:null)},value:Math.round(100*(null!==(r=null===(l=i.filters.get(a))||void 0===l?void 0:l.intensity)&&void 0!==r?r:0)),onChange:e=>{O(a,e/100)},min:-100,max:100},a)}),S&&a(n,{label:b("toolbar.curvedText")||"Curved text",enabled:!!i.curveEnabled,onEnabledChange:e=>L({curveEnabled:e}),children:[e(g,{label:b("toolbar.curvePower")||"Curve",className:"pn:py-2",children:e(m,{value:Math.round(100*i.curvePower),onValueChange:e=>{L({curvePower:k(e,-100,100)/100})},style:{width:64},min:-100,max:100})}),e(u,{textEl:i,eachSet:L})]}),S&&a(n,{label:b("toolbar.textStroke"),enabled:!!i.strokeWidth,onEnabledChange:e=>L({strokeWidth:e?2:0}),children:[e(E,{store:l,color:i.stroke,onColorChange:e=>{L({stroke:e})},value:i.strokeWidth,onValueChange:e=>{L({strokeWidth:e})},min:1,max:Math.max(1,Math.round(i.fontSize/2))}),e(g,{label:b("toolbar.strokeLineJoin"),className:"pn:py-2",children:e(f,{variant:"outline",value:[C(i.strokeLineJoin)],onValueChange:e=>{const a=e[0];a&&L({strokeLineJoin:a})},children:x.map(({value:a,labelKey:o})=>e(v,{value:a,"aria-label":b(o),title:b(o),children:e(y,{join:a})},a))})})]}),S&&a(n,{label:b("toolbar.textBackground"),enabled:!!i.backgroundEnabled,onEnabledChange:e=>L({backgroundEnabled:e}),children:[e(t,{label:b("toolbar.backgroundCornerRadius"),value:Math.round(100*i.backgroundCornerRadius),onChange:e=>L({backgroundCornerRadius:e/100}),min:0,max:100}),e(t,{label:b("toolbar.backgroundPadding"),value:Math.round(100*i.backgroundPadding),onChange:e=>L({backgroundPadding:e/100}),min:0,max:100}),e(t,{label:b("toolbar.opacity"),value:Math.round(100*i.backgroundOpacity),onChange:e=>L({backgroundOpacity:e/100}),min:0,max:100}),e(g,{label:b("toolbar.color"),className:"pn:py-2",children:e(d,{value:i.backgroundColor,size:30,onChange:e=>{L({backgroundColor:e})},store:l})})]}),z&&e(n,{label:b("toolbar.border"),enabled:!!i.borderSize,onEnabledChange:e=>L({borderSize:e?2:0}),children:e(E,{store:l,color:i.borderColor,onColorChange:e=>{L({borderColor:e})},value:i.borderSize,onValueChange:e=>{L({borderSize:e})},min:1,max:Math.max(1,Math.round(Math.min(i.width,i.height)/2))})}),z&&e(t,{label:b("toolbar.cornerRadius"),visible:z,enabled:0!==i.cornerRadius,onEnabledChange:e=>{L({cornerRadius:e?Math.min(i.width/4,i.height/4):0})},value:Math.min(i.cornerRadius,Math.round(Math.min(i.width/2,i.height/2))),onChange:e=>{L({cornerRadius:e})},min:1,max:Math.round(Math.min(i.width/2,i.height/2))}),a(n,{label:b("toolbar.shadow"),enabled:i.shadowEnabled,onEnabledChange:e=>L({shadowEnabled:e}),children:[e(t,{label:b("toolbar.blur"),value:i.shadowBlur,onChange:e=>{L({shadowBlur:e})},min:0,max:50}),e(t,{label:b("toolbar.offsetX"),value:i.shadowOffsetX,onChange:e=>{L({shadowOffsetX:e})},min:-50,max:50}),e(t,{label:b("toolbar.offsetY"),value:i.shadowOffsetY,onChange:e=>{L({shadowOffsetY:e})},min:-50,max:50}),e(t,{label:b("toolbar.opacity"),value:Math.round(100*i.shadowOpacity),onChange:e=>{L({shadowOpacity:e/100})},min:0,max:100}),e(g,{label:b("toolbar.color"),className:"pn:py-2",children:e(d,{value:i.shadowColor,size:30,onChange:e=>{L({shadowColor:e})},store:l})})]})]})});
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
2
|
import type { StoreType } from "../ui-types.js";
|
|
3
|
-
|
|
4
|
-
export declare function setUploadFunc(func: typeof uploadFunc): void;
|
|
3
|
+
export { setUploadFunc } from "../utils/file.js";
|
|
5
4
|
export declare const UploadPanel: ({ store }: {
|
|
6
5
|
store: StoreType;
|
|
7
6
|
}) => React.JSX.Element;
|
|
8
7
|
export type UploadPanelProps = {
|
|
9
8
|
store: StoreType;
|
|
10
9
|
};
|
|
11
|
-
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as i from"react";import{PolotnoIcon as
|
|
1
|
+
import{jsx as e,jsxs as t}from"react/jsx-runtime";import*as i from"react";import{PolotnoIcon as r}from"../icons/registry.js";import{getVideoPreview as o}from"../utils/video.js";import{getType as l,getUploadFunc as s}from"../utils/file.js";import{insertMediaIntoPage as n}from"../utils/insert-file.js";import{ImagesGrid as a}from"./images-grid.js";import{t as c}from"../utils/l10n.js";import{Button as p}from"../primitives/button.js";export{setUploadFunc}from"../utils/file.js";let d=[];function m(){const e=new Blob(['\n <svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100">\n <circle cx="50" cy="50" r="45" fill="#f0f0f0" stroke="#ccc" stroke-width="2"/>\n <path d="M40,35 L40,65 L55,50 L70,50 M70,35 Q80,50 70,65" fill="none" stroke="#666" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>\n </svg>\n '],{type:"image/svg+xml"});return URL.createObjectURL(e)}export const UploadPanel=({store:u})=>{const[f,g]=i.useState(d),[h,v]=i.useState(!1),y=i.useRef(null);return i.useEffect(()=>{d=f},[f]),t("div",{className:"pn:flex pn:h-full pn:flex-col",children:[e("div",{style:{height:"45px",paddingTop:"5px"},children:c("sidePanel.uploadTip")}),e("div",{style:{marginBottom:"20px"},children:t("label",{htmlFor:"input-file",children:[t(p,{variant:"outline",style:{width:"100%"},onClick:()=>{var e;null===(e=y.current)||void 0===e||e.click()},children:[e(r,{name:"action.add"}),c("sidePanel.uploadImage")]}),e("input",{type:"file",ref:y,style:{display:"none"},onChange:async e=>{var t;const{target:i}=e;v(!0);try{for(const e of Array.from(null!==(t=i.files)&&void 0!==t?t:[])){const t=await s()(e),i=l(e);let r=t;"video"===i?r=await o(t):"audio"===i&&(r=m()),g(e=>e.concat([{url:t,type:i,preview:r}]))}}catch(e){console.error(e)}v(!1),i.value=""},multiple:!0})]})}),e(a,{images:f,isLoading:h,getPreview:e=>e.preview,hideNoResults:!0,onSelect:async(e,t,i)=>{n({url:e.url,type:e.type,store:u,droppedPos:t,targetElement:i})}})]})};
|
package/toolbar/html-toolbar.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{jsx as t,jsxs as e}from"react/jsx-runtime";import o from"react";import{observer as n}from"mobx-react-lite";import{PolotnoIcon as i}from"../icons/registry.js";import{Button as l}from"../primitives/button.js";import{Tooltip as r,TooltipContent as s,TooltipTrigger as a}from"../primitives/tooltip.js";import{TooltipIconButton as c}from"../primitives/tooltip-icon-button.js";import{ColorPicker as m}from"./color-picker.js";import p from"./filters-picker.js";import{ElementContainer as u,extendToolbar as d}from"./element-container.js";import f from"../utils/styled.js";import{AnimationsPicker as x}from"./animations-picker.js";import{flags as g}from"../utils/flags.js";import{TextAiWrite as v}from"./text-ai-write.js";import{t as h}from"../utils/l10n.js";import{quillRef as b,createQuill as T,setQuillContent as y}from"../canvas/html-element.js";import{FontMenu as F,fetcher as S,TextSpacing as z,TextFontSize as j,TextTransform as C,ALIGN_OPTIONS as
|
|
1
|
+
import{jsx as t,jsxs as e}from"react/jsx-runtime";import o from"react";import{observer as n}from"mobx-react-lite";import{PolotnoIcon as i}from"../icons/registry.js";import{Button as l}from"../primitives/button.js";import{Tooltip as r,TooltipContent as s,TooltipTrigger as a}from"../primitives/tooltip.js";import{TooltipIconButton as c}from"../primitives/tooltip-icon-button.js";import{ColorPicker as m}from"./color-picker.js";import p from"./filters-picker.js";import{ElementContainer as u,extendToolbar as d}from"./element-container.js";import f from"../utils/styled.js";import{AnimationsPicker as x}from"./animations-picker.js";import{flags as g}from"../utils/flags.js";import{TextAiWrite as v}from"./text-ai-write.js";import{t as h}from"../utils/l10n.js";import{quillRef as b,createQuill as T,setQuillContent as y}from"../canvas/html-element.js";import{FontMenu as F,fetcher as S,TextSpacing as z,TextFontSize as j,TextTransform as C,ALIGN_OPTIONS as A,VERTICAL_ALIGN_OPTIONS as D,VERTICAL_ALIGN_ICONS as N}from"./text-toolbar.js";import{cycleNext as w}from"./toolbar-shared.js";import E from"swr";import{getFontsList as k,globalFonts as L,isGoogleFontChanged as I}from"../utils/fonts.js";import{getGoogleFontsListAPI as M}from"../utils/api.js";import{normalizeRichTextHtml as B,listEffectiveFontFamilies as R,isBoldWeight as W}from"../utils/rich-text-html.js";import{patchTextFormat as O}from"../utils/text-format.js";import{useTextFormat as P,getActiveTextEditor as V,resolveSelectionScope as _,applyToLiveEditor as G}from"../utils/text-format-state.js";const H=f("div")`
|
|
2
2
|
position: relative;
|
|
3
3
|
display: inline-block;
|
|
4
4
|
|
|
@@ -8,7 +8,7 @@ import{jsx as t,jsxs as e}from"react/jsx-runtime";import o from"react";import{ob
|
|
|
8
8
|
&.polotno-mixed:focus-within input {
|
|
9
9
|
color: inherit !important;
|
|
10
10
|
}
|
|
11
|
-
`,
|
|
11
|
+
`,J=f("span")`
|
|
12
12
|
position: absolute;
|
|
13
13
|
left: 11px;
|
|
14
14
|
top: 0;
|
|
@@ -22,4 +22,4 @@ import{jsx as t,jsxs as e}from"react/jsx-runtime";import o from"react";import{ob
|
|
|
22
22
|
${H}:focus-within & {
|
|
23
23
|
display: none;
|
|
24
24
|
}
|
|
25
|
-
`,
|
|
25
|
+
`,Q=t=>{const e=V();return!!e&&e.store===t&&!!e.instance};let U=null;const X=()=>{b.pendingToolbarInteraction=!0,U&&clearTimeout(U),U=setTimeout(()=>{b.pendingToolbarInteraction=!1,U=null},100)},$=t=>{var e;(!(e=t.target)||"INPUT"!==e.tagName&&"TEXTAREA"!==e.tagName&&"SELECT"!==e.tagName&&!e.isContentEditable)&&t.preventDefault(),X()},q=n(({store:e,isActive:o,toggle:n,icon:i,ariaLabel:l,tooltipContent:r})=>{const{format:s,applyTextFormat:a}=P(e);return t(c,{label:r||l||"",side:"bottom",active:o(s),onMouseDown:t=>{t.preventDefault()},onClick:()=>n(s,a),children:i})});function K(t,e){const o=t.textDecoration.value||"",n="underline"===e?"line-through":"underline";return[!o.split(/\s+/).includes(e)&&e,o.split(/\s+/).includes(n)&&n].filter(Boolean).join(" ")}export const TextBold=n(({store:e})=>t(q,{store:e,isActive:t=>W(t.fontWeight.value),toggle:(t,e)=>e({fontWeight:W(t.fontWeight.value)?400:700}),icon:t(i,{name:"text.bold",className:"pn:size-4"}),tooltipContent:h("toolbar.bold")}));export const FontStyleGroup=n(({element:o,store:n,elements:m,components:p})=>{const u=(null==p?void 0:p.TextBold)||TextBold;return e("div",{className:"pn:flex pn:items-center pn:gap-0.5",children:[t(u,{element:o,store:n}),t(q,{store:n,isActive:t=>"italic"===t.fontStyle.value,toggle:(t,e)=>e({fontStyle:"italic"===t.fontStyle.value?"normal":"italic"}),icon:t(i,{name:"text.italic",className:"pn:size-4"}),tooltipContent:h("toolbar.italic")}),t(q,{store:n,isActive:t=>{var e;return!!(null===(e=t.textDecoration.value)||void 0===e?void 0:e.split(/\s+/).includes("underline"))},toggle:(t,e)=>e({textDecoration:K(t,"underline")}),icon:t(i,{name:"text.underline",className:"pn:size-4"}),tooltipContent:h("toolbar.underline")}),t(q,{store:n,isActive:t=>{var e;return!!(null===(e=t.textDecoration.value)||void 0===e?void 0:e.split(/\s+/).includes("line-through"))},toggle:(t,e)=>e({textDecoration:K(t,"line-through")}),icon:t(i,{name:"text.strikethrough",className:"pn:size-4"}),tooltipContent:h("toolbar.strikethrough")}),t(c,{label:h("toolbar.textAlign"),side:"bottom",onClick:()=>{const t=w(A,o.align);n.history.transaction(()=>{m.forEach(e=>{e.set({align:t})})})},children:"left"===o.align?t(i,{name:"text.alignLeft",className:"pn:size-4"}):"center"===o.align?t(i,{name:"text.alignCenter",className:"pn:size-4"}):"right"===o.align?t(i,{name:"text.alignRight",className:"pn:size-4"}):t(i,{name:"text.alignJustify",className:"pn:size-4"})}),g.textVerticalResizeEnabled&&e(r,{children:[t(a,{render:t(l,{variant:"ghost",size:"icon-sm",onClick:()=>{const t=w(D,o.verticalAlign);n.history.transaction(()=>{o.set({verticalAlign:t})})},"aria-label":h("toolbar.verticalAlign"),children:N[o.verticalAlign]})}),t(s,{side:"bottom",children:h("toolbar.verticalAlign")})]}),t(c,{label:h("toolbar.listFormat"),side:"bottom",onMouseDown:t=>{t.preventDefault()},onClick:()=>{var t;let e=window.__polotnoQuill;const n=!e;e=e||(({html:t})=>{const e=document.createElement("div");document.body.appendChild(e),e.style.display="none",e.style.whiteSpace="pre-wrap";const o=T(e);return y(o,t),o})({html:o.text}),n&&e.setSelection(0,e.getLength(),"api");const i=e.getSelection(!0)||(null===(t=V())||void 0===t?void 0:t.lastSelection)||{index:0,length:e.getLength()},l=e.getFormat(i);l.list?"bullet"===l.list?e.format("list","ordered"):e.format("list",!1):e.format("list","bullet"),n&&(o.set({text:B(e.root.innerHTML,{fontSize:o.fontSize,fontFamily:o.fontFamily})}),(t=>{t.root.parentElement.remove()})(e))},children:(()=>{const e=V();return"bullet"===(e&&e.store===n?e.currentFormat:{}).list?t(i,{name:"text.numberedList",className:"pn:size-5"}):t(i,{name:"text.bulletList",className:"pn:size-5"})})()})]})});export const FontColorInput=n(({element:e,store:o})=>{var n;const{format:i,applyTextFormat:l}=P(o);return t("div",{"data-polotno-keep-focus":!0,onMouseDown:$,children:t(m,{value:null!==(n=i.fill.value)&&void 0!==n?n:e.fill,gradientEnabled:!0,onClose:()=>{const t=V();(null==t?void 0:t.instance)&&t.lastSelection&&t.instance.setSelection(t.lastSelection)},onChange:t=>l({fill:t}),store:o})})});export const DirectionInput=n(({element:e})=>{const o="rtl"===e.dir,n=h("toolbar.textDirection");return t(c,{label:n,side:"bottom",onClick:()=>{e.set({dir:o?"ltr":"rtl"})},children:t(i,o?{name:"text.paragraph",className:"pn:size-5 pn:-scale-x-100"}:{name:"text.richText",className:"pn:size-5"})})});const Y=k(),Z={TextFontFamily:n(({elements:e,store:n})=>{var i;const{format:l,applyTextFormat:r}=P(n),s=Q(n),a=l.fontFamily.mixed,c=a?Array.from(new Set(e.flatMap(t=>R(t.text,t.fontFamily)))).sort((t,e)=>t.localeCompare(e,void 0,{sensitivity:"base"})):void 0,[m,p]=o.useState(!1),{data:u,mutate:d}=E(m?M():null,S,{isPaused:()=>I(),fallbackData:[]});o.useEffect(()=>{d()},[I()]);const f=n.fonts.concat(L).map(t=>t.fontFamily).concat((null==u?void 0:u.length)&&!I()?u:Y),x=[];n.find(t=>("text"===t.type&&x.push(t.fontFamily),!1));const g=[...new Set(x.concat("_divider").concat(f))],v=null!==(i=l.fontFamily.value)&&void 0!==i?i:e[0].fontFamily;let h=v;h.length>15&&(h=h.slice(0,15)+"...");const b=t(F,{fonts:g,activeFont:v,activeFontLabel:h,store:n,mixed:a,mixedFonts:c,open:m,onOpenChange:p,onFontSelect:t=>r({fontFamily:t})});return s?t("div",{"data-polotno-keep-focus":!0,onMouseDown:$,children:b}):b}),TextFontSize:n(({elements:o,store:n})=>{const{format:i}=P(n),l=Q(n),r=i.fontSize.mixed,s=i.fontSize.value,a=o.map(t=>new Proxy(t,{get:(t,e)=>"fontSize"===e?null!=s?s:t.fontSize:"set"===e?e=>((t,e)=>{if(!e.fontSize){return void t.set(e)}const o=V();if(o&&o.store===n&&o.instance){const{scope:t,isEmpty:n}=_(o.instance,o.lastSelection);if("partial"===t||"collapsed"===t&&n){return void G(o.instance,{fontSize:e.fontSize},o.lastSelection)}}const{attrsToSet:i}=O(t,{fontSize:e.fontSize});t.set(Object.assign(Object.assign({},e),i))})(t,e):Reflect.get(t,e)})),c=e(H,{className:r?"polotno-mixed":"",children:[t(j,{elements:a,store:n}),r&&t(J,{"aria-hidden":!0,children:"—"})]});return l?t("div",{"data-polotno-keep-focus":!0,onMouseDown:X,children:c}):c}),TextFontVariant:FontStyleGroup,TextTransform:C,TextFilters:p,TextFill:FontColorInput,TextSpacing:z,TextDirection:DirectionInput,TextAnimations:x,TextAiWrite:v};export const HtmlToolbar=n(({store:e,components:o})=>{const n=e.selectedElements,i=e.selectedElements[0],l=["TextFill","TextFontFamily","TextFontSize","TextFontVariant","TextSpacing","TextTransform","TextFilters",g.animationsEnabled&&"TextAnimations",g.aiTextEnabled&&"TextAiWrite"],r=d({type:"text",usedItems:l,components:o});return t(u,{items:r,itemRender:l=>{if("TextBold"===l){return null}const r=(null==o?void 0:o[l])||Z[l];return t(r,{element:i,elements:n,store:e,components:o},l)}})});
|
package/utils/base64.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e=()=>"undefined"!=typeof globalThis?globalThis.Buffer:void 0;export const decodeBase64=o=>{if("function"==typeof atob){const e=atob(o),t=new Uint8Array(e.length);for(let o=0;o<e.length;o++){t[o]=e.charCodeAt(o)}return t}const t=e();if(t){return new Uint8Array(t.from(o,"base64"))}throw new Error("No base64 decoder available")};export const encodeBase64=o=>{if("function"==typeof btoa){let e="";for(let t=0;t<o.length;t++){e+=String.fromCharCode(o[t])}return btoa(e)}const t=e();if(t){return t.from(o).toString("base64")}throw new Error("No base64 encoder available")};
|
package/utils/clipboard.d.ts
CHANGED
|
@@ -4,3 +4,364 @@ export declare const cut: (store: StoreType) => void;
|
|
|
4
4
|
export declare const paste: (store: StoreType) => void;
|
|
5
5
|
export declare const isClipboardEmpty: () => boolean;
|
|
6
6
|
export declare const resetClipboard: () => void;
|
|
7
|
+
export declare const copyToEvent: (store: StoreType, e: ClipboardEvent) => boolean;
|
|
8
|
+
export declare const cutToEvent: (store: StoreType, e: ClipboardEvent) => boolean;
|
|
9
|
+
export declare const insertTextElement: (store: StoreType, text: string, extra?: Record<string, any>) => (import("mobx-state-tree").ModelInstanceTypeProps<{
|
|
10
|
+
id: import("mobx-state-tree").ISimpleType<string>;
|
|
11
|
+
type: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
12
|
+
name: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
13
|
+
opacity: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
14
|
+
custom: import("mobx-state-tree").IType<any, any, any>;
|
|
15
|
+
visible: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
16
|
+
selectable: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
17
|
+
removable: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
18
|
+
alwaysOnTop: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
19
|
+
showInExport: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
20
|
+
} & {
|
|
21
|
+
x: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
22
|
+
y: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
23
|
+
width: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
24
|
+
height: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
25
|
+
rotation: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
26
|
+
opacity: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
27
|
+
animations: import("mobx-state-tree").IArrayType<import("mobx-state-tree").IModelType<{
|
|
28
|
+
delay: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
29
|
+
duration: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
30
|
+
enabled: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
31
|
+
type: import("mobx-state-tree").ISimpleType<"exit" | "enter" | "loop">;
|
|
32
|
+
name: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
33
|
+
data: import("mobx-state-tree").IType<{} | null | undefined, {}, {}>;
|
|
34
|
+
}, {}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
|
|
35
|
+
blurEnabled: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
36
|
+
blurRadius: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
37
|
+
brightnessEnabled: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
38
|
+
brightness: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
39
|
+
sepiaEnabled: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
40
|
+
grayscaleEnabled: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
41
|
+
filters: import("mobx-state-tree").IMapType<import("mobx-state-tree").IModelType<{
|
|
42
|
+
intensity: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
43
|
+
}, {}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
|
|
44
|
+
shadowEnabled: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
45
|
+
shadowBlur: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
46
|
+
shadowOffsetX: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
47
|
+
shadowOffsetY: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
48
|
+
shadowColor: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
49
|
+
shadowOpacity: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
50
|
+
visible: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
51
|
+
draggable: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
52
|
+
resizable: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
53
|
+
selectable: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
54
|
+
contentEditable: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
55
|
+
styleEditable: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
56
|
+
alwaysOnTop: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
57
|
+
showInExport: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
58
|
+
} & {
|
|
59
|
+
type: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
60
|
+
text: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
61
|
+
placeholder: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
62
|
+
fontSize: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
63
|
+
fontFamily: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
64
|
+
fontStyle: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
65
|
+
fontWeight: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
66
|
+
textDecoration: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
67
|
+
textTransform: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
68
|
+
fill: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
69
|
+
align: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
70
|
+
width: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
71
|
+
height: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
72
|
+
verticalAlign: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
73
|
+
strokeWidth: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
74
|
+
stroke: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
75
|
+
strokeLineJoin: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
76
|
+
lineHeight: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree/dist/internal").IUnionType<[import("mobx-state-tree").ISimpleType<number>, import("mobx-state-tree").ISimpleType<string>]>, [undefined]>;
|
|
77
|
+
letterSpacing: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
78
|
+
_editModeEnabled: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
79
|
+
backgroundEnabled: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
80
|
+
backgroundColor: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
81
|
+
backgroundOpacity: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
82
|
+
backgroundCornerRadius: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
83
|
+
backgroundPadding: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
84
|
+
legacyBackground: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<boolean>>;
|
|
85
|
+
curveEnabled: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
86
|
+
curvePower: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
87
|
+
}> & {
|
|
88
|
+
readonly page: any;
|
|
89
|
+
readonly store: any;
|
|
90
|
+
readonly top: import("mobx-state-tree").ModelInstanceTypeProps<{
|
|
91
|
+
id: import("mobx-state-tree").ISimpleType<string>;
|
|
92
|
+
type: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
93
|
+
name: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
94
|
+
opacity: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
95
|
+
custom: import("mobx-state-tree").IType<any, any, any>;
|
|
96
|
+
visible: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
97
|
+
selectable: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
98
|
+
removable: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
99
|
+
alwaysOnTop: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
100
|
+
showInExport: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
101
|
+
}> & import("mobx-state-tree").IStateTreeNode<import("mobx-state-tree").IModelType<{
|
|
102
|
+
id: import("mobx-state-tree").ISimpleType<string>;
|
|
103
|
+
type: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
104
|
+
name: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
105
|
+
opacity: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
106
|
+
custom: import("mobx-state-tree").IType<any, any, any>;
|
|
107
|
+
visible: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
108
|
+
selectable: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
109
|
+
removable: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
110
|
+
alwaysOnTop: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
111
|
+
showInExport: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
112
|
+
}, {}, import("mobx-state-tree").ModelCreationType<{
|
|
113
|
+
id: string;
|
|
114
|
+
type: string | undefined;
|
|
115
|
+
name: string | undefined;
|
|
116
|
+
opacity: number | undefined;
|
|
117
|
+
custom: any;
|
|
118
|
+
visible: boolean | undefined;
|
|
119
|
+
selectable: boolean | undefined;
|
|
120
|
+
removable: boolean | undefined;
|
|
121
|
+
alwaysOnTop: boolean | undefined;
|
|
122
|
+
showInExport: boolean | undefined;
|
|
123
|
+
}>, import("mobx-state-tree").ModelSnapshotType<{
|
|
124
|
+
id: import("mobx-state-tree").ISimpleType<string>;
|
|
125
|
+
type: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
126
|
+
name: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
127
|
+
opacity: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
128
|
+
custom: import("mobx-state-tree").IType<any, any, any>;
|
|
129
|
+
visible: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
130
|
+
selectable: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
131
|
+
removable: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
132
|
+
alwaysOnTop: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
133
|
+
showInExport: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
134
|
+
}>>>;
|
|
135
|
+
readonly parent: any;
|
|
136
|
+
readonly zIndex: any;
|
|
137
|
+
} & {
|
|
138
|
+
toJSON(): {
|
|
139
|
+
id: string;
|
|
140
|
+
type: string;
|
|
141
|
+
name: string;
|
|
142
|
+
opacity: number;
|
|
143
|
+
custom: any;
|
|
144
|
+
visible: boolean;
|
|
145
|
+
selectable: boolean;
|
|
146
|
+
removable: boolean;
|
|
147
|
+
alwaysOnTop: boolean;
|
|
148
|
+
showInExport: boolean;
|
|
149
|
+
};
|
|
150
|
+
} & {
|
|
151
|
+
clone(attrs?: any, { skipSelect }?: {
|
|
152
|
+
skipSelect?: boolean | undefined;
|
|
153
|
+
}): import("../model/node-model.js").NodeType;
|
|
154
|
+
set(attrs: any): void;
|
|
155
|
+
moveUp(): void;
|
|
156
|
+
moveTop(): void;
|
|
157
|
+
moveDown(): void;
|
|
158
|
+
moveBottom(): void;
|
|
159
|
+
setZIndex(zIndex: number): void;
|
|
160
|
+
beforeDestroy(): void;
|
|
161
|
+
} & {
|
|
162
|
+
readonly locked: boolean;
|
|
163
|
+
readonly a: import("../model/shape-model.js").AnimatedAttrs;
|
|
164
|
+
animated(attr: any): any;
|
|
165
|
+
readonly timeRange: {
|
|
166
|
+
start: number;
|
|
167
|
+
end: number;
|
|
168
|
+
};
|
|
169
|
+
readonly active: boolean;
|
|
170
|
+
readonly isSelected: boolean;
|
|
171
|
+
readonly isSelectedDirectly: boolean;
|
|
172
|
+
} & {
|
|
173
|
+
setAnimation(type: any, attrs: any): void;
|
|
174
|
+
setFilter(type: any, value: any): void;
|
|
175
|
+
} & {
|
|
176
|
+
set(attrs: any): void;
|
|
177
|
+
afterCreate(): void;
|
|
178
|
+
toggleEditMode(editing?: boolean): void;
|
|
179
|
+
beforeDestroy(): void;
|
|
180
|
+
} & import("mobx-state-tree").IStateTreeNode<import("mobx-state-tree").IModelType<{
|
|
181
|
+
id: import("mobx-state-tree").ISimpleType<string>;
|
|
182
|
+
type: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
183
|
+
name: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
184
|
+
opacity: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
185
|
+
custom: import("mobx-state-tree").IType<any, any, any>;
|
|
186
|
+
visible: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
187
|
+
selectable: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
188
|
+
removable: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
189
|
+
alwaysOnTop: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
190
|
+
showInExport: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
191
|
+
} & {
|
|
192
|
+
x: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
193
|
+
y: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
194
|
+
width: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
195
|
+
height: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
196
|
+
rotation: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
197
|
+
opacity: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
198
|
+
animations: import("mobx-state-tree").IArrayType<import("mobx-state-tree").IModelType<{
|
|
199
|
+
delay: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
200
|
+
duration: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
201
|
+
enabled: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
202
|
+
type: import("mobx-state-tree").ISimpleType<"exit" | "enter" | "loop">;
|
|
203
|
+
name: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
204
|
+
data: import("mobx-state-tree").IType<{} | null | undefined, {}, {}>;
|
|
205
|
+
}, {}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
|
|
206
|
+
blurEnabled: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
207
|
+
blurRadius: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
208
|
+
brightnessEnabled: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
209
|
+
brightness: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
210
|
+
sepiaEnabled: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
211
|
+
grayscaleEnabled: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
212
|
+
filters: import("mobx-state-tree").IMapType<import("mobx-state-tree").IModelType<{
|
|
213
|
+
intensity: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
214
|
+
}, {}, import("mobx-state-tree")._NotCustomized, import("mobx-state-tree")._NotCustomized>>;
|
|
215
|
+
shadowEnabled: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
216
|
+
shadowBlur: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
217
|
+
shadowOffsetX: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
218
|
+
shadowOffsetY: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
219
|
+
shadowColor: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
220
|
+
shadowOpacity: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
221
|
+
visible: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
222
|
+
draggable: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
223
|
+
resizable: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
224
|
+
selectable: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
225
|
+
contentEditable: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
226
|
+
styleEditable: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
227
|
+
alwaysOnTop: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
228
|
+
showInExport: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
229
|
+
} & {
|
|
230
|
+
type: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
231
|
+
text: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
232
|
+
placeholder: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
233
|
+
fontSize: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
234
|
+
fontFamily: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
235
|
+
fontStyle: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
236
|
+
fontWeight: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
237
|
+
textDecoration: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
238
|
+
textTransform: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
239
|
+
fill: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
240
|
+
align: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
241
|
+
width: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
242
|
+
height: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
243
|
+
verticalAlign: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
244
|
+
strokeWidth: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
245
|
+
stroke: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
246
|
+
strokeLineJoin: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
247
|
+
lineHeight: import("mobx-state-tree").IOptionalIType<import("mobx-state-tree/dist/internal").IUnionType<[import("mobx-state-tree").ISimpleType<number>, import("mobx-state-tree").ISimpleType<string>]>, [undefined]>;
|
|
248
|
+
letterSpacing: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
249
|
+
_editModeEnabled: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
250
|
+
backgroundEnabled: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
251
|
+
backgroundColor: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
252
|
+
backgroundOpacity: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
253
|
+
backgroundCornerRadius: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
254
|
+
backgroundPadding: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
255
|
+
legacyBackground: import("mobx-state-tree").IMaybe<import("mobx-state-tree").ISimpleType<boolean>>;
|
|
256
|
+
curveEnabled: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
257
|
+
curvePower: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
258
|
+
}, {
|
|
259
|
+
readonly page: any;
|
|
260
|
+
readonly store: any;
|
|
261
|
+
readonly top: import("mobx-state-tree").ModelInstanceTypeProps<{
|
|
262
|
+
id: import("mobx-state-tree").ISimpleType<string>;
|
|
263
|
+
type: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
264
|
+
name: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
265
|
+
opacity: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
266
|
+
custom: import("mobx-state-tree").IType<any, any, any>;
|
|
267
|
+
visible: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
268
|
+
selectable: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
269
|
+
removable: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
270
|
+
alwaysOnTop: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
271
|
+
showInExport: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
272
|
+
}> & import("mobx-state-tree").IStateTreeNode<import("mobx-state-tree").IModelType<{
|
|
273
|
+
id: import("mobx-state-tree").ISimpleType<string>;
|
|
274
|
+
type: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
275
|
+
name: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
276
|
+
opacity: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
277
|
+
custom: import("mobx-state-tree").IType<any, any, any>;
|
|
278
|
+
visible: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
279
|
+
selectable: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
280
|
+
removable: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
281
|
+
alwaysOnTop: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
282
|
+
showInExport: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
283
|
+
}, {}, import("mobx-state-tree").ModelCreationType<{
|
|
284
|
+
id: string;
|
|
285
|
+
type: string | undefined;
|
|
286
|
+
name: string | undefined;
|
|
287
|
+
opacity: number | undefined;
|
|
288
|
+
custom: any;
|
|
289
|
+
visible: boolean | undefined;
|
|
290
|
+
selectable: boolean | undefined;
|
|
291
|
+
removable: boolean | undefined;
|
|
292
|
+
alwaysOnTop: boolean | undefined;
|
|
293
|
+
showInExport: boolean | undefined;
|
|
294
|
+
}>, import("mobx-state-tree").ModelSnapshotType<{
|
|
295
|
+
id: import("mobx-state-tree").ISimpleType<string>;
|
|
296
|
+
type: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
297
|
+
name: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
298
|
+
opacity: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
299
|
+
custom: import("mobx-state-tree").IType<any, any, any>;
|
|
300
|
+
visible: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
301
|
+
selectable: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
302
|
+
removable: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
303
|
+
alwaysOnTop: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
304
|
+
showInExport: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
305
|
+
}>>>;
|
|
306
|
+
readonly parent: any;
|
|
307
|
+
readonly zIndex: any;
|
|
308
|
+
} & {
|
|
309
|
+
toJSON(): {
|
|
310
|
+
id: string;
|
|
311
|
+
type: string;
|
|
312
|
+
name: string;
|
|
313
|
+
opacity: number;
|
|
314
|
+
custom: any;
|
|
315
|
+
visible: boolean;
|
|
316
|
+
selectable: boolean;
|
|
317
|
+
removable: boolean;
|
|
318
|
+
alwaysOnTop: boolean;
|
|
319
|
+
showInExport: boolean;
|
|
320
|
+
};
|
|
321
|
+
} & {
|
|
322
|
+
clone(attrs?: any, { skipSelect }?: {
|
|
323
|
+
skipSelect?: boolean | undefined;
|
|
324
|
+
}): import("../model/node-model.js").NodeType;
|
|
325
|
+
set(attrs: any): void;
|
|
326
|
+
moveUp(): void;
|
|
327
|
+
moveTop(): void;
|
|
328
|
+
moveDown(): void;
|
|
329
|
+
moveBottom(): void;
|
|
330
|
+
setZIndex(zIndex: number): void;
|
|
331
|
+
beforeDestroy(): void;
|
|
332
|
+
} & {
|
|
333
|
+
readonly locked: boolean;
|
|
334
|
+
readonly a: import("../model/shape-model.js").AnimatedAttrs;
|
|
335
|
+
animated(attr: any): any;
|
|
336
|
+
readonly timeRange: {
|
|
337
|
+
start: number;
|
|
338
|
+
end: number;
|
|
339
|
+
};
|
|
340
|
+
readonly active: boolean;
|
|
341
|
+
readonly isSelected: boolean;
|
|
342
|
+
readonly isSelectedDirectly: boolean;
|
|
343
|
+
} & {
|
|
344
|
+
setAnimation(type: any, attrs: any): void;
|
|
345
|
+
setFilter(type: any, value: any): void;
|
|
346
|
+
} & {
|
|
347
|
+
set(attrs: any): void;
|
|
348
|
+
afterCreate(): void;
|
|
349
|
+
toggleEditMode(editing?: boolean): void;
|
|
350
|
+
beforeDestroy(): void;
|
|
351
|
+
}, any, import("mobx-state-tree").ModelSnapshotType<{
|
|
352
|
+
id: import("mobx-state-tree").ISimpleType<string>;
|
|
353
|
+
type: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
354
|
+
name: import("mobx-state-tree").IType<string | undefined, string, string>;
|
|
355
|
+
opacity: import("mobx-state-tree").IType<number | undefined, number, number>;
|
|
356
|
+
custom: import("mobx-state-tree").IType<any, any, any>;
|
|
357
|
+
visible: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
358
|
+
selectable: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
359
|
+
removable: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
360
|
+
alwaysOnTop: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
361
|
+
showInExport: import("mobx-state-tree").IType<boolean | undefined, boolean, boolean>;
|
|
362
|
+
}>>> & {
|
|
363
|
+
type: "text";
|
|
364
|
+
}) | undefined;
|
|
365
|
+
export declare const pasteFromEvent: (store: StoreType, e: ClipboardEvent, opts?: {
|
|
366
|
+
onText?: (text: string) => void;
|
|
367
|
+
}) => boolean;
|
package/utils/clipboard.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{forEveryChild as e}from"../model/group-model.js";import{
|
|
1
|
+
import{forEveryChild as e}from"../model/group-model.js";import{nanoid as t}from"nanoid";import{getTotalClientRect as a}from"./math.js";import{removeTags as o}from"./text.js";import{insertFileIntoPage as r}from"./insert-file.js";import{decodeBase64 as l,encodeBase64 as n}from"./base64.js";let i={data:[],pageId:"",payloadId:""};const d="polotno_clipboard",s=(e,t,a)=>{i={data:JSON.parse(JSON.stringify(e)),pageId:t||"",payloadId:a||""};try{localStorage.setItem(d,JSON.stringify(e)),localStorage.setItem(d+"_page",t||""),localStorage.setItem(d+"_payload",a||"")}catch(o){}},c=()=>{try{const e=localStorage.getItem(d),t=localStorage.getItem(d+"_page"),a=localStorage.getItem(d+"_payload");if(e){return{data:JSON.parse(e),pageId:t,payloadId:a}}}catch(e){}return i},p="data-polotno-clipboard";export const copy=e=>{var t;0!==e.selectedElements.length&&s(e.selectedElements.map(e=>e.toJSON()),null===(t=e.activePage)||void 0===t?void 0:t.id)};export const cut=e=>{if(0===e.selectedElements.length){return}copy(e);const t=e.selectedElements.filter(e=>e.removable).map(e=>e.id);e.deleteElements(t)};const m=(t,o)=>{t.history.transaction(()=>{var r,l;let n=0,i=0;const{data:d,pageId:c,payloadId:p}=o;if(c===(null===(r=t.activePage)||void 0===r?void 0:r.id)){n=t.width/20,i=t.height/20}else{const o=[];e({children:d},e=>{"group"!==e.type&&o.push(e)});const r=a(o);r.maxX>t.width&&(n=-r.minX),r.maxY>t.height&&(i=-r.minY)}const m=[];e({children:d},e=>{delete e.id,"group"!==e.type&&(e.x+=n,e.y+=i)}),d.forEach(e=>{var a;const o=null===(a=t.activePage)||void 0===a?void 0:a.addElement(e);o&&m.push(o.id)}),s(d,null===(l=t.activePage)||void 0===l?void 0:l.id,p),t.selectElements(m)})};export const paste=e=>{m(e,c())};export const isClipboardEmpty=()=>0===c().data.length;export const resetClipboard=()=>{i={data:[],pageId:"",payloadId:""};try{localStorage.removeItem(d),localStorage.removeItem(d+"_page"),localStorage.removeItem(d+"_payload")}catch(e){}};export const copyToEvent=(a,r)=>{var l,i;if(!r.clipboardData||0===a.selectedElements.length){return!1}const d=a.selectedElements.map(e=>e.toJSON()),c=t(),m={v:1,id:c,pageId:(null===(l=a.activePage)||void 0===l?void 0:l.id)||"",elements:d};r.clipboardData.setData("text/html",`<div ${p}="${(e=>n((new TextEncoder).encode(JSON.stringify(e))))(m)}"></div>`);const g=[];return e({children:d},e=>{"text"===e.type&&g.push(o(e.text))}),r.clipboardData.setData("text/plain",g.join("\n")||" "),r.preventDefault(),s(d,null===(i=a.activePage)||void 0===i?void 0:i.id,c),!0};export const cutToEvent=(e,t)=>{const a=copyToEvent(e,t);if(a){const t=e.selectedElements.filter(e=>e.removable).map(e=>e.id);e.deleteElements(t)}return a};export const insertTextElement=(e,t,a={})=>{var o;const r=e.width/2,l=(e.width+e.height)/2160;return null===(o=e.activePage)||void 0===o?void 0:o.addElement(Object.assign({type:"text",x:e.width/2-r/2,y:e.height/2-15,width:r,fontSize:30*l,text:t},a))};export const pasteFromEvent=(e,t,a={})=>{const o=t.clipboardData;if(!o){return!1}const n=o.getData("text/html");if(n&&n.includes(p)){const a=(e=>{var a;try{const t=null===(a=(new DOMParser).parseFromString(e,"text/html").querySelector(`[${p}]`))||void 0===a?void 0:a.getAttribute(p);if(!t){return null}const o=JSON.parse((new TextDecoder).decode(l(t)));return Array.isArray(o.elements)?o:null}catch(t){return null}})(n);if(a){t.preventDefault();const o=c();return a.id&&a.id===o.payloadId?m(e,o):m(e,{data:a.elements,pageId:a.pageId,payloadId:a.id}),!0}}const i=o.files?Array.from(o.files):[];if(i.length>0){return t.preventDefault(),(async()=>{for(const a of i){try{await r({file:a,store:e})}catch(t){console.error("polotno: failed to insert pasted file",t)}}})(),!0}const d=o.getData("text/plain");if(d&&d.trim()){if(t.preventDefault(),a.onText){a.onText(d)}else{const t=insertTextElement(e,(e=>e.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">"))(d));t&&e.selectElements([t.id])}return!0}return 0===o.types.length&&0!==c().data.length&&(t.preventDefault(),paste(e),!0)};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type PolotnoErrorCode = 'DESIGN_INVALID' | 'EXPORT_FAILED' | 'IMAGE_FAILED' | 'FONT_FAILED' | 'VIDEO_FAILED' | 'UNKNOWN';
|
|
2
|
+
export interface PolotnoError extends Error {
|
|
3
|
+
code: PolotnoErrorCode;
|
|
4
|
+
details?: Record<string, any>;
|
|
5
|
+
cause?: unknown;
|
|
6
|
+
}
|
|
7
|
+
export declare function polotnoError(code: PolotnoErrorCode, message: string, details?: Record<string, any>, cause?: unknown): PolotnoError;
|
package/utils/errors.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function polotnoError(o,r,e,n){const t=new Error(r);return t.code=o,void 0!==e&&(t.details=e),void 0!==n&&(t.cause=n),t}
|
package/utils/file.d.ts
CHANGED
|
@@ -1 +1,7 @@
|
|
|
1
1
|
export declare function localFileToURL(file: File): Promise<string>;
|
|
2
|
+
export type MediaType = 'image' | 'svg' | 'video' | 'audio' | 'gif';
|
|
3
|
+
export declare function getType(file: File): MediaType;
|
|
4
|
+
declare let uploadFunc: (file: File) => Promise<string>;
|
|
5
|
+
export declare function setUploadFunc(func: typeof uploadFunc): void;
|
|
6
|
+
export declare function getUploadFunc(): (file: File) => Promise<string>;
|
|
7
|
+
export {};
|
package/utils/file.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export async function localFileToURL(
|
|
1
|
+
export async function localFileToURL(o){return new Promise((e,n)=>{const i=new FileReader;i.readAsDataURL(o),i.onload=()=>e(i.result),i.onerror=o=>n(o)})}export function getType(o){const{type:e}=o;return e.indexOf("svg")>=0?"svg":e.indexOf("gif")>=0?"gif":e.indexOf("image")>=0?"image":e.indexOf("video")>=0?"video":e.indexOf("audio")>=0?"audio":"image"}let o=async o=>(console.warn("Polotno: using data URL for file embeding. This is not recommended for production. Set upload function https://polotno.com/docs/editor-configuration#how-to-change-image-upload-behavior"),localFileToURL(o));export function setUploadFunc(e){o=e}export function getUploadFunc(){return o}
|
package/utils/fonts.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import*as t from"mobx";import{triggerLoadError as o,getFontLoadTimeout as n}from"./loader.js";import{
|
|
1
|
+
import*as t from"mobx";import{triggerLoadError as o,getFontLoadTimeout as n}from"./loader.js";import{polotnoError as e}from"./errors.js";import{removeTags as r}from"./text.js";let s=t.observable(["Roboto","Amatic SC","Press Start 2P","Marck Script","Rubik Mono One"]),a=t.observable({value:!1});export function isGoogleFontChanged(){return a.value}export function setGoogleFonts(t){"default"!==t?(a.value=!0,s.splice(0,s.length),s.push(...t)):a.value=!1}export function getFontsList(){return s}export const globalFonts=t.observable([]);export function addGlobalFont(t){globalFonts.push(t)}export function removeGlobalFont(t){const o=globalFonts.findIndex(o=>o.fontFamily===t);-1!==o&&globalFonts.splice(o,1)}export function replaceGlobalFonts(t){globalFonts.replace(t)}const i="BESbswy 0123456789 Il1Ww",l=["sans-serif","serif","monospace"];function c(t){const o=function(t=""){const o=r(t).replace(/\s+/g," ").trim();return o?Array.from(o).slice(0,10).join(""):""}(t);return o?`${i} ${o}`:i}export function _getFontProbeTextForTesting(t){return c(t)}let u;function d(t){return{width:t.width,actualBoundingBoxLeft:t.actualBoundingBoxLeft||0,actualBoundingBoxRight:t.actualBoundingBoxRight||0,actualBoundingBoxAscent:t.actualBoundingBoxAscent||0,actualBoundingBoxDescent:t.actualBoundingBoxDescent||0}}function f(t="sans-serif",o="normal",n="normal",e=i){u||(u=document.createElement("canvas"));const r=u.getContext("2d");return r.font=`${o} ${n} 40px ${t}`,d(r.measureText(e))}function m(t,o,n,e,r){return l.some(s=>{const a=function(t,o="sans-serif",n="normal",e="normal",r=i){u||(u=document.createElement("canvas"));const s=u.getContext("2d");return s.font=`${n} ${e} 40px '${t}', ${o}`,d(s.measureText(r))}(t,s,o,n,e);return function(t,o,n=.01){return Math.abs(t.width-o.width)>n||Math.abs(t.actualBoundingBoxLeft-o.actualBoundingBoxLeft)>n||Math.abs(t.actualBoundingBoxRight-o.actualBoundingBoxRight)>n||Math.abs(t.actualBoundingBoxAscent-o.actualBoundingBoxAscent)>n||Math.abs(t.actualBoundingBoxDescent-o.actualBoundingBoxDescent)>n}(a,r[s])})}export function measureFontDom(t,o="sans-serif",n="normal",e="normal",r=i){if("undefined"==typeof document||!document.body){return 0}const s=document.createElement("span");s.textContent=r,s.style.cssText=`\n position:absolute;\n visibility:hidden;\n white-space:nowrap;\n top:-9999px;\n left:-9999px;\n font:${n} ${e} 90px '${t}', ${o};\n `,document.body.appendChild(s);const a=s.getBoundingClientRect().width;return s.remove(),a}const g={Arial:!0};export const isFontLoaded=(t,o,n)=>o&&n?!!g[`${t}_${o}_${n}`]:Object.keys(g).some(o=>o.startsWith(t+"_"))||!!g[t];export function _setFontLoadedForTesting(t,o){o?g[t]=!0:delete g[t]}export async function loadFont(t,r,s,a){var i;const l=`${t}_${r}_${s}`;if(g[l]){return}const u=!!(null===(i=document.fonts)||void 0===i?void 0:i.load),d=c(a),$={"sans-serif":f("sans-serif",r,s,d),serif:f("serif",r,s,d),monospace:f("monospace",r,s,d)};if(u){try{if(await document.fonts.load(`${r} ${s} 16px '${t}'`,d),m(t,r,s,d,$)){return void F(l,t)}}catch(y){}}const b=Math.min(6e3,n())/60;for(let n=0;n<b;n++){if("missing"===x[t]){if(!h.has(t)){h.add(t),setTimeout(()=>h.delete(t),B);const n=`Font "${t}" not found: not registered and no matching Google Font.`;console.error(n),o(e("FONT_FAILED",n,{family:t,reason:"not-found"}))}return}if(t in p&&!p[t]&&"errored"===x[t]&&injectGoogleFont(t),u){try{await document.fonts.load(`${r} ${s} 16px '${t}'`,d)}catch(v){}}if(m(t,r,s,d,$)){return void F(l,t)}await new Promise(t=>setTimeout(t,60))}console.warn(`Timeout for loading font "${t}". Looks like polotno can't load it. Is it a correct font family?`),o(e("FONT_FAILED",`Timeout for loading font "${t}"`,{family:t,reason:"timeout"}))}const p={},x={},h=new Set,B=500;function F(t,o){g[t]=!0,delete x[o]}let $="400,400italic,700,700italic";export function setGoogleFontsVariants(t){$=t}export function getGoogleFontsVariants(){return $}export function getGoogleFontsUrl(t){return`https://fonts.googleapis.com/css?family=${t.replace(/ /g,"+")}:${$}`}export function injectGoogleFont(t){if(p[t]){return}const o=getGoogleFontsUrl(t),n=document.createElement("link");n.type="text/css",n.href=o,n.rel="stylesheet",n.onerror=()=>{n.remove(),p[t]=!1,"errored"===x[t]?function(t){x[t]="probing",fetch(getGoogleFontsUrl(t),{mode:"no-cors"}).then(()=>{x[t]="missing"}).catch(()=>{delete x[t]})}(t):x[t]||(x[t]="errored")},document.getElementsByTagName("head")[0].appendChild(n),p[t]=!0}const b={};let y;export function injectCustomFont(t){const o=t.fontFamily;if(b[o]){return}if(!t.url&&!t.styles){return}delete x[o];const n=t.styles||(t.url?[{src:`url("${t.url}")`}]:[]),e=(y||(y=document.getElementById("polotno-font-style"),y||(y=document.createElement("style"),y.id="polotno-font-style",document.head.appendChild(y)),y)).sheet;n.forEach(t=>{e.insertRule(`\n @font-face{\n font-family:'${o}';\n src:${t.src};\n font-style:${t.fontStyle||"normal"};\n font-weight:${t.fontWeight||"normal"};\n font-display:swap; /* optional but recommended */\n }`,e.cssRules.length)}),b[t.fontFamily]=!0}
|