polotno 4.1.3 → 4.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/blueprint/side-panel/select-video.d.ts +10 -0
  2. package/blueprint/toolbar/html-toolbar.js +2 -2
  3. package/canvas/drawing-layer.d.ts +3 -2
  4. package/canvas/drawing-layer.js +1 -1
  5. package/canvas/element.js +1 -1
  6. package/canvas/hotkeys.js +1 -1
  7. package/canvas/page-controls.js +1 -1
  8. package/canvas/page.js +1 -1
  9. package/canvas/quill-font-formats.js +1 -1
  10. package/canvas/render-tag-element.js +1 -1
  11. package/canvas/rich-editor.d.ts +3 -1
  12. package/canvas/rich-editor.js +16 -3
  13. package/canvas/rules.js +1 -1
  14. package/canvas/text-element/font-specs-loader.d.ts +3 -0
  15. package/canvas/text-element/font-specs-loader.js +1 -0
  16. package/canvas/workspace-canvas.js +1 -1
  17. package/config.d.ts +1 -1
  18. package/config.js +1 -1
  19. package/icons/registry.d.ts +2 -0
  20. package/icons/registry.js +1 -1
  21. package/model/figure-model.d.ts +5 -0
  22. package/model/gif-model.d.ts +5 -0
  23. package/model/group-model.d.ts +40 -0
  24. package/model/group-model.js +1 -1
  25. package/model/image-model.d.ts +5 -0
  26. package/model/line-model.d.ts +5 -0
  27. package/model/page-model.d.ts +56 -0
  28. package/model/page-model.js +1 -1
  29. package/model/shape-model.d.ts +5 -0
  30. package/model/shape-model.js +1 -1
  31. package/model/store.d.ts +521 -0
  32. package/model/store.js +1 -1
  33. package/model/svg-model.d.ts +5 -0
  34. package/model/table-model.d.ts +5 -0
  35. package/model/text-model.d.ts +5 -0
  36. package/model/video-model.d.ts +5 -0
  37. package/package.json +5 -4
  38. package/pages-timeline/current-time.js +1 -1
  39. package/pages-timeline/element-track.js +1 -1
  40. package/pages-timeline/elements.js +1 -1
  41. package/pages-timeline/page-preview.js +1 -1
  42. package/pages-timeline/play-button.js +1 -1
  43. package/polotno.bundle.js +205 -129
  44. package/side-panel/select-video.d.ts +10 -0
  45. package/side-panel/size-panel.js +1 -1
  46. package/themes/carbon.css +157 -0
  47. package/toolbar/download-button.js +1 -1
  48. package/toolbar/html-toolbar.js +4 -4
  49. package/toolbar/image-toolbar.js +1 -1
  50. package/toolbar/text-toolbar.js +1 -1
  51. package/toolbar/video-toolbar.js +1 -1
  52. package/ui.css +1 -1
  53. package/utils/l10n.d.ts +8 -0
  54. package/utils/l10n.js +1 -1
  55. package/utils/rich-text-html.d.ts +12 -0
  56. package/utils/rich-text-html.js +1 -1
  57. package/utils/split-element.d.ts +2 -0
  58. package/utils/split-element.js +1 -0
  59. package/utils/text-format-state.js +1 -1
  60. package/utils/text-format.d.ts +2 -2
  61. package/utils/text-format.js +1 -1
  62. package/utils/text.js +1 -1
  63. package/utils/timeline.d.ts +3 -0
  64. package/utils/timeline.js +1 -1
  65. package/utils/to-pptx.js +1 -1
  66. package/utils/validate-key.js +1 -1
package/model/store.js CHANGED
@@ -1 +1 @@
1
- var e=this&&this.__rest||function(e,t){var i={};for(var o in e){Object.prototype.hasOwnProperty.call(e,o)&&t.indexOf(o)<0&&(i[o]=e[o])}if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var n=0;for(o=Object.getOwnPropertySymbols(e);n<o.length;n++){t.indexOf(o[n])<0&&Object.prototype.propertyIsEnumerable.call(e,o[n])&&(i[o[n]]=e[o[n]])}}return i};import{applySnapshot as t,cast as i,destroy as o,detach as n,getSnapshot as a,onSnapshot as s,setLivelinessChecking as r,types as l}from"mobx-state-tree";import{UndoManager as d}from"./history.js";import{nanoid as c}from"nanoid";import p from"konva";import{computed as g}from"mobx";import{downloadFile as m}from"../utils/download.js";import{getJsPDF as u}from"../utils/pdf.js";import{createGIF as f}from"../utils/gif-lib.js";import{validateKey as h,setKey as b}from"../utils/validate-key.js";import*as y from"../utils/fonts.js";import{flags as v}from"../utils/flags.js";import{addDpiMetadataToImage as P}from"../utils/image-dpi.js";import{nodeToCanvas as w}from"../utils/canvas.js";import{whenLoaded as E}from"../utils/loader.js";import{pxToUnit as x}from"../utils/unit.js";import{deepEqual as I}from"../utils/deep-equal.js";import{waitTillAvailable as _}from"../utils/wait.js";import{jsonToHTML as k}from"../utils/to-html.js";import{jsonToSVG as S}from"../utils/to-svg.js";import{Page as T}from"./page-model.js";import{forEveryChild as O,forEveryNode as j}from"./group-model.js";import{Audio as R}from"./audio-model.js";r("ignore");export const Font=l.model("Font",{fontFamily:l.string,url:l.optional(l.string,""),styles:l.frozen()}).preProcessSnapshot(e=>Object.assign(Object.assign({},e),{fontFamily:e.fontFamily||e.name}));export const ROLES={ADMIN:"admin",VIEWER:"viewer"};export const Store=l.model("Store",{role:"",pages:l.array(T),fonts:l.array(Font),audios:l.array(R),width:1080,height:1080,currentTime:0,isPlaying:!1,scale:1,scaleToFit:1,unit:l.optional(l.enumeration("UnitType",["pt","mm","cm","in","px"]),"px"),dpi:72,schemaVersion:4,bleedVisible:!1,rulesVisible:!1,distanceGuidesVisible:!1,openedSidePanel:"",previousOpenedSidePanel:"",custom:l.frozen(),tool:l.optional(l.enumeration("Tool",["selection","draw","pan","text","eraser"]),"selection"),toolOptions:l.optional(l.model({brushType:l.optional(l.enumeration("BrushType",["brush","highlighter"]),"brush"),strokeWidth:l.optional(l.number,5),stroke:l.optional(l.string,"#000000"),opacity:l.optional(l.number,1)}),{}),selectedElementsIds:l.array(l.string),animatedElementsIds:l.array(l.string),history:l.optional(d,{targetPath:"../pages"}),_elementsPixelRatio:Math.min(2,"undefined"!=typeof window&&window.devicePixelRatio||1),_activePageId:"",_selectedPagesIds:l.array(l.string),_forceShowCredit:!1,_validated:!1}).views(e=>{const t=g(()=>{const t={};return j({children:e.pages},e=>(t[e.id]=e,!1)),t},{keepAlive:!0});return{get _idsMap(){return t.get()}}}).views(e=>({get _bleedVisible(){return console.warn("store._bleedVisible is deprecated. Please use store.bleedVisible instead."),e.bleedVisible},get selectedElements(){return e.selectedElementsIds.map(t=>e._idsMap[t]).filter(e=>!!e)},get children(){return e.pages},get selectedShapes(){const e=[];return O({children:this.selectedElements},t=>{"group"!==t.type&&e.push(t)}),e},get activePage(){return e.pages.slice().find(t=>t.id===e._activePageId)||(e.pages.length?e.pages[0]:null)},get selectedPages(){return e._selectedPagesIds.map(t=>e.pages.find(e=>e.id===t))},get duration(){let t=0;return e.pages.forEach(e=>{t+=e.duration}),t},get _hasCroppedImages(){return this.find(e=>"image"===e.type&&e._cropModeEnabled)},find(t){let i;return j({children:e.pages},e=>{if(!i&&t(e)){return i=e,!0}}),i},getElementById:t=>e._idsMap[t]})).actions(r=>{let l=0,d=null,g=!1;const b={afterCreate(){r.history.canUndo},setCurrentTime(e){r.currentTime=e},_togglePlaying(e=!r.isPlaying){r.isPlaying=e},play({animatedElementsIds:e=[],startTime:t=0,currentTime:o=0,endTime:n=r.duration,repeat:a=!1}={}){o&&(console.warn("currentTime property of store.play() is deprecated. Please use startTime instead."),t=o),r.animatedElementsIds=i(e),r.currentTime=t,r.isPlaying=!0,l=Date.now(),d=n,g=a,requestAnimationFrame(()=>b.seek())},checkActivePage(){let e=0;for(const t of r.pages){if(r.currentTime>=t.startTime&&r.currentTime<t.startTime+t.duration){b.selectPage(t.id);break}e+=t.duration}},seek(){if(!r.isPlaying){return}const e=Date.now(),t=e-l;l=e,r.currentTime+=t,b.checkActivePage();const i=d||r.duration;r.isPlaying&&r.currentTime<i?requestAnimationFrame(()=>b.seek()):r.isPlaying&&g?(r.currentTime=0,requestAnimationFrame(()=>b.seek())):b.stop()},stop(){r.isPlaying=!1,r.currentTime=0,r.animatedElementsIds=i([]),b.checkActivePage()},__(){r._validated||(h(r._forceShowCredit),r._validated=!0)},set(e){Object.assign(r,e)},setUnit({unit:e,dpi:t}){r.unit=e||r.unit,r.dpi=t||r.dpi},setRole(e){r.role=e},setTool(e){r.tool=e},setToolOptions(e){Object.assign(r.toolOptions,e)},addPage(e){const t=T.create(Object.assign({id:c(10)},e));return r.pages.push(t),r._activePageId=t.id,t},selectPage(e){r._activePageId=e,1===r._selectedPagesIds.length&&(r._selectedPagesIds=i([e]))},selectPages(e){r._selectedPagesIds=i(e),1===r._selectedPagesIds.length&&(r._activePageId=r._selectedPagesIds[0])},selectElements(e){const t=e.map(e=>r.getElementById(e)).filter(e=>!!e);t.sort((e,t)=>{var i,o,n,a;return(null!==(o=null===(i=e.parent)||void 0===i?void 0:i.children.indexOf(e))&&void 0!==o?o:0)-(null!==(a=null===(n=t.parent)||void 0===n?void 0:n.children.indexOf(t))&&void 0!==a?a:0)}),r.selectedElementsIds=i(t.map(e=>e.id))},toggleBleed(e){r.bleedVisible=null!=e?e:!r.bleedVisible},toggleRulers(e){r.rulesVisible=null!=e?e:!r.rulesVisible},toggleDistanceGuides(e){r.distanceGuidesVisible=null!=e?e:!r.distanceGuidesVisible},openSidePanel(e){r.openedSidePanel!==e&&(r.previousOpenedSidePanel=r.openedSidePanel,r.openedSidePanel=e)},restoreSidePanel(){const e=r.previousOpenedSidePanel;e&&e!==r.openedSidePanel?r.openedSidePanel=e:r.openedSidePanel="photos"},setScale(e){r.scale=e},_setScaleToFit(e){r.scaleToFit=e},setElementsPixelRatio(e){r._elementsPixelRatio=e},setSize(e,t,i){r.pages.forEach(o=>{o.setSize({width:e,height:t,useMagic:i,softChange:!0})}),r.width=e,r.height=t},setPageZIndex(e,t){const i=r.pages.find(t=>t.id===e);i&&(n(i),r.pages.remove(i),r.pages.splice(t,0,i))},deletePages(e){const t=r.pages.indexOf(r.activePage);e.forEach(e=>{const t=r.pages.find(t=>t.id===e);o(t)});const n=Math.min(r.pages.length-1,t),a=r.pages[n];a&&(r._activePageId=a.id),r.selectedElementsIds=i(r.selectedElementsIds.filter(e=>r.getElementById(e)))},groupElements(e,t={}){const o=e.map(e=>r.getElementById(e)).filter(e=>!!e);if(!o.length){return}const a=o[0].parent;if(!a){return}if(!o.every(e=>e.parent===a)){return void console.warn("store.groupElements: refusing to group elements that do not share a parent. Pass ids whose elements all live under the same page or the same group.")}o.forEach(e=>n(e));const s=a.children.reduce((e,t)=>{var i;if("group"===t.type){const o=null===(i=t.name)||void 0===i?void 0:i.match(/group-(\d+)/);if(o){const t=parseInt(o[1],10);return Math.max(e,t)}}return e},0),l=Object.assign({id:c(10),name:`group-${s+1}`,children:o,type:"group"},t);return a.children.push(l),r.selectedElementsIds=i([l.id]),a.children.find(e=>e.id===l.id)},ungroupElements(e){const t=e.map(e=>r.getElementById(e)),o=[];t.forEach(e=>{if(e&&"group"===e.type){const t=e.parent;if(!t){return}const i=t.children.indexOf(e);e.children.forEach(e=>{o.push(e.id)}),e.children.slice().forEach(e=>{n(e),t.children.push(e)}),t.children.splice(i,1)}}),r.selectedElementsIds=i(o)},deleteElements(e){const t=[];r.find(i=>(e.includes(i.id)&&t.push(i),!1)),t.forEach(e=>{o(e)}),r.selectedElementsIds=i(r.selectedElementsIds.filter(e=>r.getElementById(e)))},on(e,t){if("change"===e){let e=b.toJSON();return s(r,i=>{const o=b.toJSON();!I(e,o)&&(e=o,t(o))})}},async _toCanvas({pixelRatio:e,ignoreBackground:t,pageId:i,mimeType:o,includeBleed:n,_skipTimeout:a,quickMode:s=!1,_exportCanvases:l}={}){var d;const c=e||1;i=i||(null===(d=r.pages[0])||void 0===d?void 0:d.id);const g=r.pages.find(e=>e.id===i);if(!g){throw new Error(`No page for export with id ${i}`)}const m=r._elementsPixelRatio;c>r._elementsPixelRatio&&b.setElementsPixelRatio(c),s?null==g||g.set({_forceMount:!0}):null==g||g.set({_exporting:!0});const u=await _(()=>{const e=p.stages.filter(e=>e.getAttr("pageId")===i);return 0===e.length?null:e});if(!u){throw null==g||g.set({_forceMount:!1,_exporting:!1}),b.setElementsPixelRatio(m),new Error(`Export is failed. Can not find stage for page ${i}. Looks like <Workspace /> component is not mounted, but it is required in order to process the export.`)}u.length>1&&console.error(`Polotno error: Detected several canvas elements for page "${i}" in the document. This is not supported and will lead to incorrect export. Make sure to use unique ids for all pages and make sure you unmount <Workspace /> when it is not needed.`);const f=u[0];await b.waitLoading({_skipTimeout:a});const h=f.findOne(".page-container");if(!h){throw b.setElementsPixelRatio(m),null==g||g.set({_forceMount:!1,_exporting:!1}),new Error("Export is failed. Canvas was unmounted.")}const y=f.position();f.position({x:0,y:0}),f.find("Transformer").forEach(e=>{e.setAttr("oldVisible",e.visible()),e.visible(!1)}),h.find(".page-background").forEach(e=>e.shadowEnabled(!1)),h.find(".page-background").forEach(e=>e.strokeEnabled(!1)),h.find(".highlighter").forEach(e=>e.visible(!1));const v=h.findOne(".page-background-group"),P=v.clip();v.clip({x:null,y:null,width:null,height:null});const E=h.findOne(".elements-container"),x=E.clip();E.clip({x:null,y:null,width:null,height:null});const I=h.find(e=>!e.visible()&&e.getAttr("editModeEnabled")&&!e.getAttr("hideInExport"));I.forEach(e=>{e.setAttr("oldVisible",e.visible()),e.show()});const k=h.find(e=>e.getAttr("hideInExport"));k.forEach(e=>{e.setAttr("oldVisible",e.visible()),e.hide()}),t&&h.find(".page-background").forEach(e=>e.hide());const S=n?g.bleed:0;let T=S;!r.bleedVisible&&n||(r.bleedVisible||n?r.bleedVisible&&n?T=0:r.bleedVisible&&!n&&(T=-g.bleed):T=0);const O=g.computedWidth+2*S,j=g.computedHeight+2*S,R=h.scale();h.scale({x:1,y:1});const F=w(h,{x:h.x()-T,y:h.y()-T,width:O,height:j,pixelRatio:c,sceneCanvas:null==l?void 0:l.sceneCanvas,bufferCanvas:null==l?void 0:l.bufferCanvas});h.scale(R);const C=F._canvas;if("image/jpeg"===o){const e=C.getContext("2d");e.save(),e.globalCompositeOperation="destination-over",e.fillStyle="white",e.fillRect(0,0,C.width,C.height),e.restore()}return t&&h.find(".page-background").forEach(e=>e.show()),k.forEach(e=>{e.visible(e.getAttr("oldVisible"))}),I.forEach(e=>{e.visible(e.getAttr("oldVisible"))}),h.find(".page-background").forEach(e=>e.shadowEnabled(!0)),h.find(".page-background").forEach(e=>e.strokeEnabled(!0)),f.find("Transformer").forEach(e=>{e.visible(e.getAttr("oldVisible"))}),h.find(".highlighter").forEach(e=>e.visible(!0)),v.clip(P),E.clip(x),f.position(y),null==g||g.set({_exporting:!1,_forceMount:!1}),await Promise.resolve(),b.setElementsPixelRatio(m),C},async toDataURL(t={}){var{mimeType:i,quality:o,dpi:n,dpiMetadata:a="auto"}=t,s=e(t,["mimeType","quality","dpi","dpiMetadata"]);const l=await b._toCanvas(Object.assign({mimeType:i},s)),d=i||"image/png",c=l.toDataURL(d,o);p.Util.releaseCanvas(l);const g=null!=n?n:r.dpi;return"image/png"!==d&&"image/jpeg"!==d||"never"===a||"auto"===a&&72===g?c:P(c,d,g)},async toBlob(t={}){var{mimeType:i,quality:o}=t,n=e(t,["mimeType","quality"]);const a=await b._toCanvas(Object.assign({mimeType:i},n)),s=await new Promise(e=>{a.toBlob(e,i,o)});return p.Util.releaseCanvas(a),s},async saveAsImage(t={}){var{fileName:i}=t,o=e(t,["fileName"]);const n=(o.mimeType||"image/png").split("/")[1];m(await b.toDataURL(o),i||"polotno."+n)},async _toPDF(e){const t=e.dpi||r.dpi,i=e.parallel||1,o=e.unit||("px"===r.unit?"mm":r.unit),n=e.pixelRatio||1,a=e.pageIds||(e.pageId?[e.pageId]:r.pages.map(e=>e.id)),s=r.pages.filter(e=>a.includes(e.id)),l=await u(),d=e=>x({px:e,unit:o,dpi:t}),c=e.cropMarkSize||0,p=d(c),g=s[0]||{},m=e.includeBleed?g.bleed:0,f=d(g.computedWidth+2*m+2*p),h=d(g.computedHeight+2*m+2*p);var y=new l({unit:o,orientation:f>h?"landscape":"portrait",format:[f,h],compress:!0,putOnlyUsedFonts:!0});y.deletePage(1);const v=((e,t)=>{const i=[];for(let o=0;o<e.length;o+=t){i.push(e.slice(o,o+t))}return i})(s,i);let P=0;for(const r of v){const t=r.map(async t=>{const i=e.includeBleed?t.bleed:0,o=t.computedWidth+2*i+2*c,s=t.computedHeight+2*i+2*c,r=d(o),l=d(s);let p=0,g=n;for(;p<10;){p+=1;const i=await b.toDataURL(Object.assign(Object.assign({},e),{pageId:t.id,pixelRatio:g,dpiMetadata:"never"}));if(i.length>20){return g!==n&&console.error(`Polotno can not export PDF with current settings. Quality is automatically reduced. pixelRatio was reduced to ${parseFloat(g.toFixed(3))}.`),e.onProgress&&e.onProgress(++P/a.length*.9),{url:i,width:r,height:l,widthPx:o,heightPx:s}}g*=.8}});(await Promise.all(t)).filter(e=>void 0!==e).forEach(({url:e,width:t,height:i,widthPx:n,heightPx:a})=>{y.addPage([t,i],t>i?"landscape":"portrait");const s=y.getCurrentPageInfo();var r;switch(o){case"pt":r=1;break;case"mm":r=72/25.4;break;case"cm":r=72/2.54;break;case"in":r=72;break;case"px":r=.75;break;default:throw"Invalid unit: "+o}if(s.pageContext.cropBox={bottomLeftX:0,bottomLeftY:0,topRightX:t*r,topRightY:i*r},s.pageContext.artBox={bottomLeftX:d(c+m)*r,bottomLeftY:d(c+m)*r,topRightX:d(n-c-m)*r,topRightY:d(a-c-m)*r},s.pageContext.bleedBox={bottomLeftX:d(c+m)*r,bottomLeftY:d(c+m)*r,topRightX:d(n-c-m)*r,topRightY:d(a-c-m)*r},p){y.setLineWidth(d(1));const e=p+d(m);y.line(e,0,e,p),y.line(0,e,p,e),y.line(t-e,0,t-e,p),y.line(t,e,t-p,e),y.line(0,i-e,p,i-e),y.line(e,i,e,i-p),y.line(t,i-e,t-p,i-e),y.line(t-e,i,t-e,i-p)}y.addImage(e,p,p,t-2*p,i-2*p,void 0,"FAST")})}return y},toPDFDataURL:async e=>(await b._toPDF(Object.assign({mimeType:"image/jpeg"},e))).output("datauristring"),async toGIFDataURL(e={}){const t=e.pixelRatio||1,i=e.pageIds||(e.pageId?[e.pageId]:r.pages.map(e=>e.id)),o=r.pages.filter(e=>i.includes(e.id));if(!o.length){throw new Error("No pages found for GIF export")}const n=o[0],a=await f({width:n.computedWidth*t,height:n.computedHeight*t}),s=1e3/(e.fps||10);for(const l of o){const e=Math.max(1,Math.floor(l.duration/s));for(let i=0;i<e;i++){const e=l.startTime+i*s||1;b.setCurrentTime(e);for(const t of r.pages){t.set({_rendering:t.id===l.id})}const o=await b._toCanvas({pixelRatio:t,pageId:l.id,_skipTimeout:!0});a.addFrame(o.getContext("2d"),{delay:s,copy:!0})}}for(const l of r.pages){l.set({_rendering:!1})}return b.stop(),a.render(),new Promise(e=>{a.on("finished",function(t){!function(e,t){var i=new FileReader;i.onload=function(e){t(e.target.result)},i.readAsDataURL(e)}(t,e)})})},async saveAsGIF(t={}){var{fileName:i}=t,o=e(t,["fileName"]);const n=await b.toGIFDataURL(o);m(n,i||"polotno.gif")},async toHTML({elementHook:e}={}){const t=b.toJSON();return k({json:t,elementHook:e})},async saveAsHTML({fileName:e,elementHook:t}={}){const i=await b.toHTML({elementHook:t}),o="data:text/html;base64,"+window.btoa(unescape(encodeURIComponent(i)));m(o,e||"polotno.html")},async toSVG({elementHook:e,pageId:t,fontEmbedding:i="inline"}={fontEmbedding:"inline"}){var o;const n=b.toJSON();t=t||(null===(o=n.pages[0])||void 0===o?void 0:o.id);const a=n.pages.find(e=>e.id===t);return S({json:Object.assign(Object.assign({},n),{pages:a?[a]:[]}),elementHook:e,fontEmbedding:i})},async saveAsSVG({fileName:e,elementHook:t,pageId:i,fontEmbedding:o="inline"}={}){const n=await b.toSVG({elementHook:t,pageId:i,fontEmbedding:o}),a="data:text/svg;base64,"+window.btoa(unescape(encodeURIComponent(n)));m(a,e||"polotno.svg")},async saveAsPDF(t={}){var{fileName:i}=t,o=e(t,["fileName"]);(await b._toPDF(Object.assign({mimeType:"image/jpeg"},o))).save(i||"polotno.pdf")},async waitLoading({_skipTimeout:e=!1}={}){e||await new Promise(e=>setTimeout(e,50)),await E()},toJSON:()=>({width:r.width,height:r.height,fonts:a(r.fonts),pages:a(r.pages),audios:a(r.audios),unit:r.unit,dpi:r.dpi,custom:r.custom,schemaVersion:r.schemaVersion}),loadJSON(e,i=!1){var o,n,s;const l="boolean"==typeof i?i:null!==(o=null==i?void 0:i.keepHistory)&&void 0!==o&&o,d="boolean"!=typeof i&&null!==(n=null==i?void 0:i.modernizeTextBackground)&&void 0!==n&&n,c=JSON.parse(JSON.stringify(e)),p=c.schemaVersion||0;p<1&&(v.htmlRenderEnabled||v.renderTagTextEnabled)&&j({children:c.pages},e=>{if("text"===e.type){const t=16,i=e.letterSpacing*t;e.letterSpacing=i/e.fontSize}}),p<2&&j({children:c.pages},e=>{e.filters&&Object.keys(e.filters).forEach(t=>{if(["warm","cold","natural"].includes(t)){return}const i=e.filters[t];i&&"number"==typeof i.intensity&&(i.intensity=i.intensity/100)})}),p<3&&(v.htmlRenderEnabled||v.renderTagTextEnabled)&&!d&&j({children:c.pages},e=>{"text"===e.type&&e.backgroundEnabled&&(e.legacyBackground=!0)}),delete c.schemaVersion;const g=r.activePage?r.pages.indexOf(r.activePage):0;let m=null===(s=c.pages[g]||c.pages[0])||void 0===s?void 0:s.id;c._activePageId=m;const u=Object.assign({},a(r));Object.assign(u,c),u.history=l?a(r.history):{history:[],undoIdx:-1,targetPath:""},t(r,u)},clear({keepHistory:e=!1}={}){const t=r.pages.map(e=>e.id);b.deletePages(t),r.custom=null,e||r.history.clear()},addFont(e){b.removeFont(e.fontFamily),r.fonts.push(e)},removeFont(e){r.fonts.filter(t=>t.fontFamily===e).forEach(e=>o(e))},addAudio(e){const t=R.create(Object.assign({id:c(10)},e));r.audios.push(t)},removeAudio(e){const t=r.audios.find(t=>t.id===e);t&&r.audios.remove(t)},async loadFont(e,t,i,o){const n=r.fonts.find(t=>t.fontFamily===e)||y.globalFonts.find(t=>t.fontFamily===e);let a=[{fontStyle:"normal",fontWeight:"normal"},{fontStyle:"normal",fontWeight:"bold"}];return n?(n.styles&&(a=n.styles.map(e=>({fontStyle:e.fontStyle||"normal",fontWeight:e.fontWeight||"normal"}))),y.injectCustomFont(n)):y.injectGoogleFont(e),t&&i&&!a.some(e=>e.fontStyle===t&&e.fontWeight===i)&&a.push({fontStyle:t,fontWeight:i}),Promise.all(a.map(t=>y.loadFont(e,t.fontStyle,t.fontWeight,o)))},validate:e=>Store.validate(e,[{path:"",type:Store}]).map(e=>({path:"store"+e.context.map(e=>e.path).join("."),message:e.message}))};return b});export function createStore({key:e,showCredit:t}={key:"",showCredit:!1}){return b(e),Store.create({_forceShowCredit:t})}export default createStore;
1
+ var e=this&&this.__rest||function(e,t){var i={};for(var o in e){Object.prototype.hasOwnProperty.call(e,o)&&t.indexOf(o)<0&&(i[o]=e[o])}if(null!=e&&"function"==typeof Object.getOwnPropertySymbols){var n=0;for(o=Object.getOwnPropertySymbols(e);n<o.length;n++){t.indexOf(o[n])<0&&Object.prototype.propertyIsEnumerable.call(e,o[n])&&(i[o[n]]=e[o[n]])}}return i};import{applySnapshot as t,cast as i,destroy as o,detach as n,getSnapshot as a,onSnapshot as s,setLivelinessChecking as r,types as l}from"mobx-state-tree";import{UndoManager as d}from"./history.js";import{nanoid as c}from"nanoid";import p from"konva";import{computed as g}from"mobx";import{ZERO_BLEED as m}from"@polotno/schema";import{downloadFile as u}from"../utils/download.js";import{getJsPDF as f}from"../utils/pdf.js";import{createGIF as h}from"../utils/gif-lib.js";import{validateKey as b,setKey as y}from"../utils/validate-key.js";import*as v from"../utils/fonts.js";import{flags as P}from"../utils/flags.js";import{addDpiMetadataToImage as w}from"../utils/image-dpi.js";import{nodeToCanvas as E}from"../utils/canvas.js";import{whenLoaded as x}from"../utils/loader.js";import{pxToUnit as T}from"../utils/unit.js";import{deepEqual as I}from"../utils/deep-equal.js";import{waitTillAvailable as _}from"../utils/wait.js";import{jsonToHTML as k}from"../utils/to-html.js";import{jsonToSVG as S}from"../utils/to-svg.js";import{Page as O}from"./page-model.js";import{forEveryChild as j,forEveryNode as R}from"./group-model.js";import{Audio as F}from"./audio-model.js";r("ignore");export const Font=l.model("Font",{fontFamily:l.string,url:l.optional(l.string,""),styles:l.frozen()}).preProcessSnapshot(e=>Object.assign(Object.assign({},e),{fontFamily:e.fontFamily||e.name}));export const ROLES={ADMIN:"admin",VIEWER:"viewer"};export const Store=l.model("Store",{role:"",pages:l.array(O),fonts:l.array(Font),audios:l.array(F),width:1080,height:1080,currentTime:0,isPlaying:!1,scale:1,scaleToFit:1,unit:l.optional(l.enumeration("UnitType",["pt","mm","cm","in","px"]),"px"),dpi:72,schemaVersion:4,bleedVisible:!1,rulesVisible:!1,distanceGuidesVisible:!1,timingPreview:l.optional(l.enumeration("TimingPreview",["all","playhead"]),"all"),openedSidePanel:"",previousOpenedSidePanel:"",custom:l.frozen(),tool:l.optional(l.enumeration("Tool",["selection","draw","pan","text","eraser"]),"selection"),toolOptions:l.optional(l.model({brushType:l.optional(l.enumeration("BrushType",["brush","highlighter"]),"brush"),strokeWidth:l.optional(l.number,5),stroke:l.optional(l.string,"#000000"),opacity:l.optional(l.number,1)}),{}),selectedElementsIds:l.array(l.string),animatedElementsIds:l.array(l.string),history:l.optional(d,{targetPath:"../pages"}),_elementsPixelRatio:Math.min(2,"undefined"!=typeof window&&window.devicePixelRatio||1),_activePageId:"",_selectedPagesIds:l.array(l.string),_forceShowCredit:!1,_validated:!1}).views(e=>{const t=g(()=>{const t={};return R({children:e.pages},e=>(t[e.id]=e,!1)),t},{keepAlive:!0});return{get _idsMap(){return t.get()}}}).views(e=>({get _bleedVisible(){return console.warn("store._bleedVisible is deprecated. Please use store.bleedVisible instead."),e.bleedVisible},get selectedElements(){return e.selectedElementsIds.map(t=>e._idsMap[t]).filter(e=>!!e)},get children(){return e.pages},get selectedShapes(){const e=[];return j({children:this.selectedElements},t=>{"group"!==t.type&&e.push(t)}),e},get activePage(){return e.pages.slice().find(t=>t.id===e._activePageId)||(e.pages.length?e.pages[0]:null)},get selectedPages(){return e._selectedPagesIds.map(t=>e.pages.find(e=>e.id===t))},get duration(){let t=0;return e.pages.forEach(e=>{t+=e.duration}),t},pageAtTime(t){for(const i of e.pages){if(t>=i.startTime&&t<i.startTime+i.duration){return i}}return e.pages.length&&t>=this.duration?e.pages[e.pages.length-1]:null},get effectiveTime(){if(e.isPlaying){return e.currentTime}const t=this.activePage;return t&&this.pageAtTime(e.currentTime)!==t?t.startTime:e.currentTime},get playheadAccurate(){return e.isPlaying||"playhead"===e.timingPreview},get isEditingPaused(){var t;return!e.isPlaying&&!(null===(t=this.activePage)||void 0===t?void 0:t._exportingOrRendering)},get _hasCroppedImages(){return this.find(e=>"image"===e.type&&e._cropModeEnabled)},find(t){let i;return R({children:e.pages},e=>{if(!i&&t(e)){return i=e,!0}}),i},getElementById:t=>e._idsMap[t]})).actions(r=>{let l=0,d=null,g=!1;const y={afterCreate(){r.history.canUndo},setCurrentTime(e){r.currentTime=e},_togglePlaying(e=!r.isPlaying){r.isPlaying=e},play({animatedElementsIds:e=[],startTime:t=0,currentTime:o=0,endTime:n=r.duration,repeat:a=!1}={}){o&&(console.warn("currentTime property of store.play() is deprecated. Please use startTime instead."),t=o),r.animatedElementsIds=i(e),r.currentTime=t,r.isPlaying=!0,l=Date.now(),d=n,g=a,requestAnimationFrame(()=>y.seek())},checkActivePage(){const e=r.pageAtTime(r.currentTime);e&&y.selectPage(e.id)},seek(){if(!r.isPlaying){return}const e=Date.now(),t=e-l;l=e,r.currentTime+=t;const i=d||r.duration;r.currentTime>=i&&!g&&(r.currentTime=i),y.checkActivePage(),r.isPlaying&&r.currentTime<i?requestAnimationFrame(()=>y.seek()):r.isPlaying&&g?(r.currentTime=0,requestAnimationFrame(()=>y.seek())):y.pause()},pause(){r.isPlaying=!1,r.animatedElementsIds=i([])},stop(){y.pause(),r.currentTime=0,y.checkActivePage()},__(){r._validated||(b(r._forceShowCredit),r._validated=!0)},set(e){Object.assign(r,e)},setUnit({unit:e,dpi:t}){r.unit=e||r.unit,r.dpi=t||r.dpi},setRole(e){r.role=e},setTool(e){r.tool=e},setToolOptions(e){Object.assign(r.toolOptions,e)},addPage(e){const t=O.create(Object.assign({id:c(10)},e));return r.pages.push(t),r._activePageId=t.id,t},selectPage(e){r._activePageId=e,1===r._selectedPagesIds.length&&(r._selectedPagesIds=i([e]))},selectPages(e){r._selectedPagesIds=i(e),1===r._selectedPagesIds.length&&(r._activePageId=r._selectedPagesIds[0])},selectElements(e){const t=e.map(e=>r.getElementById(e)).filter(e=>!!e);t.sort((e,t)=>{var i,o,n,a;return(null!==(o=null===(i=e.parent)||void 0===i?void 0:i.children.indexOf(e))&&void 0!==o?o:0)-(null!==(a=null===(n=t.parent)||void 0===n?void 0:n.children.indexOf(t))&&void 0!==a?a:0)}),r.selectedElementsIds=i(t.map(e=>e.id))},toggleBleed(e){r.bleedVisible=null!=e?e:!r.bleedVisible},toggleRulers(e){r.rulesVisible=null!=e?e:!r.rulesVisible},setTimingPreview(e){r.timingPreview=e},toggleDistanceGuides(e){r.distanceGuidesVisible=null!=e?e:!r.distanceGuidesVisible},openSidePanel(e){r.openedSidePanel!==e&&(r.previousOpenedSidePanel=r.openedSidePanel,r.openedSidePanel=e)},restoreSidePanel(){const e=r.previousOpenedSidePanel;e&&e!==r.openedSidePanel?r.openedSidePanel=e:r.openedSidePanel="photos"},setScale(e){r.scale=e},_setScaleToFit(e){r.scaleToFit=e},setElementsPixelRatio(e){r._elementsPixelRatio=e},setSize(e,t,i){r.pages.forEach(o=>{o.setSize({width:e,height:t,useMagic:i,softChange:!0})}),r.width=e,r.height=t},setPageZIndex(e,t){const i=r.pages.find(t=>t.id===e);i&&(n(i),r.pages.remove(i),r.pages.splice(t,0,i))},deletePages(e){const t=r.pages.indexOf(r.activePage);e.forEach(e=>{const t=r.pages.find(t=>t.id===e);o(t)});const n=Math.min(r.pages.length-1,t),a=r.pages[n];a&&(r._activePageId=a.id),r.selectedElementsIds=i(r.selectedElementsIds.filter(e=>r.getElementById(e)))},groupElements(e,t={}){const o=e.map(e=>r.getElementById(e)).filter(e=>!!e);if(!o.length){return}const a=o[0].parent;if(!a){return}if(!o.every(e=>e.parent===a)){return void console.warn("store.groupElements: refusing to group elements that do not share a parent. Pass ids whose elements all live under the same page or the same group.")}o.forEach(e=>n(e));const s=a.children.reduce((e,t)=>{var i;if("group"===t.type){const o=null===(i=t.name)||void 0===i?void 0:i.match(/group-(\d+)/);if(o){const t=parseInt(o[1],10);return Math.max(e,t)}}return e},0),l=Object.assign({id:c(10),name:`group-${s+1}`,children:o,type:"group"},t);return a.children.push(l),r.selectedElementsIds=i([l.id]),a.children.find(e=>e.id===l.id)},ungroupElements(e){const t=e.map(e=>r.getElementById(e)),o=[];t.forEach(e=>{if(e&&"group"===e.type){const t=e.parent;if(!t){return}const i=t.children.indexOf(e);e.children.forEach(e=>{o.push(e.id)}),e.children.slice().forEach(e=>{n(e),t.children.push(e)}),t.children.splice(i,1)}}),r.selectedElementsIds=i(o)},deleteElements(e){const t=[];r.find(i=>(e.includes(i.id)&&t.push(i),!1)),t.forEach(e=>{o(e)}),r.selectedElementsIds=i(r.selectedElementsIds.filter(e=>r.getElementById(e)))},on(e,t){if("change"===e){let e=y.toJSON();return s(r,i=>{const o=y.toJSON();!I(e,o)&&(e=o,t(o))})}},async _toCanvas({pixelRatio:e,ignoreBackground:t,pageId:i,mimeType:o,includeBleed:n,_skipTimeout:a,quickMode:s=!1,_exportCanvases:l}={}){var d;const c=e||1;i=i||(null===(d=r.pages[0])||void 0===d?void 0:d.id);const g=r.pages.find(e=>e.id===i);if(!g){throw new Error(`No page for export with id ${i}`)}const u=r._elementsPixelRatio;c>r._elementsPixelRatio&&y.setElementsPixelRatio(c),s?null==g||g.set({_forceMount:!0}):null==g||g.set({_exporting:!0});const f=await _(()=>{const e=p.stages.filter(e=>e.getAttr("pageId")===i);return 0===e.length?null:e});if(!f){throw null==g||g.set({_forceMount:!1,_exporting:!1}),y.setElementsPixelRatio(u),new Error(`Export is failed. Can not find stage for page ${i}. Looks like <Workspace /> component is not mounted, but it is required in order to process the export.`)}f.length>1&&console.error(`Polotno error: Detected several canvas elements for page "${i}" in the document. This is not supported and will lead to incorrect export. Make sure to use unique ids for all pages and make sure you unmount <Workspace /> when it is not needed.`);const h=f[0];await y.waitLoading({_skipTimeout:a});const b=h.findOne(".page-container");if(!b){throw y.setElementsPixelRatio(u),null==g||g.set({_forceMount:!1,_exporting:!1}),new Error("Export is failed. Canvas was unmounted.")}const v=h.position();h.position({x:0,y:0}),h.find("Transformer").forEach(e=>{e.setAttr("oldVisible",e.visible()),e.visible(!1)}),b.find(".page-background").forEach(e=>e.shadowEnabled(!1)),b.find(".page-background").forEach(e=>e.strokeEnabled(!1)),b.find(".highlighter").forEach(e=>e.visible(!1));const P=b.findOne(".page-background-group"),w=P.clip();P.clip({x:null,y:null,width:null,height:null});const x=b.findOne(".elements-container"),T=x.clip();x.clip({x:null,y:null,width:null,height:null});const I=b.find(e=>!e.visible()&&e.getAttr("editModeEnabled")&&!e.getAttr("hideInExport"));I.forEach(e=>{e.setAttr("oldVisible",e.visible()),e.show()});const k=b.find(e=>e.getAttr("hideInExport"));k.forEach(e=>{e.setAttr("oldVisible",e.visible()),e.hide()}),t&&b.find(".page-background").forEach(e=>e.hide());const S=n?g.computedBleed:m;let O=S.left,j=S.top;!r.bleedVisible&&n||(r.bleedVisible||n?r.bleedVisible&&n?(O=0,j=0):r.bleedVisible&&!n&&(O=-g.computedBleed.left,j=-g.computedBleed.top):(O=0,j=0));const R=g.computedWidth+S.left+S.right,F=g.computedHeight+S.top+S.bottom,C=b.scale();b.scale({x:1,y:1});const V=E(b,{x:b.x()-O,y:b.y()-j,width:R,height:F,pixelRatio:c,sceneCanvas:null==l?void 0:l.sceneCanvas,bufferCanvas:null==l?void 0:l.bufferCanvas});b.scale(C);const A=V._canvas;if("image/jpeg"===o){const e=A.getContext("2d");e.save(),e.globalCompositeOperation="destination-over",e.fillStyle="white",e.fillRect(0,0,A.width,A.height),e.restore()}return t&&b.find(".page-background").forEach(e=>e.show()),k.forEach(e=>{e.visible(e.getAttr("oldVisible"))}),I.forEach(e=>{e.visible(e.getAttr("oldVisible"))}),b.find(".page-background").forEach(e=>e.shadowEnabled(!0)),b.find(".page-background").forEach(e=>e.strokeEnabled(!0)),h.find("Transformer").forEach(e=>{e.visible(e.getAttr("oldVisible"))}),b.find(".highlighter").forEach(e=>e.visible(!0)),P.clip(w),x.clip(T),h.position(v),null==g||g.set({_exporting:!1,_forceMount:!1}),await Promise.resolve(),y.setElementsPixelRatio(u),A},async toDataURL(t={}){var{mimeType:i,quality:o,dpi:n,dpiMetadata:a="auto"}=t,s=e(t,["mimeType","quality","dpi","dpiMetadata"]);const l=await y._toCanvas(Object.assign({mimeType:i},s)),d=i||"image/png",c=l.toDataURL(d,o);p.Util.releaseCanvas(l);const g=null!=n?n:r.dpi;return"image/png"!==d&&"image/jpeg"!==d||"never"===a||"auto"===a&&72===g?c:w(c,d,g)},async toBlob(t={}){var{mimeType:i,quality:o}=t,n=e(t,["mimeType","quality"]);const a=await y._toCanvas(Object.assign({mimeType:i},n)),s=await new Promise(e=>{a.toBlob(e,i,o)});return p.Util.releaseCanvas(a),s},async saveAsImage(t={}){var{fileName:i}=t,o=e(t,["fileName"]);const n=(o.mimeType||"image/png").split("/")[1];u(await y.toDataURL(o),i||"polotno."+n)},async _toPDF(e){const t=e.dpi||r.dpi,i=e.parallel||1,o=e.unit||("px"===r.unit?"mm":r.unit),n=e.pixelRatio||1,a=e.pageIds||(e.pageId?[e.pageId]:r.pages.map(e=>e.id)),s=r.pages.filter(e=>a.includes(e.id)),l=await f(),d=e=>T({px:e,unit:o,dpi:t}),c=e.cropMarkSize||0,p=d(c),g=s[0]||{},u=e.includeBleed&&g.computedBleed||m,h=d(g.computedWidth+u.left+u.right+2*p),b=d(g.computedHeight+u.top+u.bottom+2*p);var v=new l({unit:o,orientation:h>b?"landscape":"portrait",format:[h,b],compress:!0,putOnlyUsedFonts:!0});v.deletePage(1);const P=((e,t)=>{const i=[];for(let o=0;o<e.length;o+=t){i.push(e.slice(o,o+t))}return i})(s,i);let w=0;for(const r of P){const t=r.map(async t=>{const i=e.includeBleed?t.computedBleed:m,o=t.computedWidth+i.left+i.right+2*c,s=t.computedHeight+i.top+i.bottom+2*c,r=d(o),l=d(s);let p=0,g=n;for(;p<10;){p+=1;const d=await y.toDataURL(Object.assign(Object.assign({},e),{pageId:t.id,pixelRatio:g,dpiMetadata:"never"}));if(d.length>20){return g!==n&&console.error(`Polotno can not export PDF with current settings. Quality is automatically reduced. pixelRatio was reduced to ${parseFloat(g.toFixed(3))}.`),e.onProgress&&e.onProgress(++w/a.length*.9),{url:d,width:r,height:l,widthPx:o,heightPx:s,cb:i}}g*=.8}});(await Promise.all(t)).filter(e=>void 0!==e).forEach(({url:e,width:t,height:i,widthPx:n,heightPx:a,cb:s})=>{v.addPage([t,i],t>i?"landscape":"portrait");const r=v.getCurrentPageInfo();var l;switch(o){case"pt":l=1;break;case"mm":l=72/25.4;break;case"cm":l=72/2.54;break;case"in":l=72;break;case"px":l=.75;break;default:throw"Invalid unit: "+o}if(r.pageContext.cropBox={bottomLeftX:0,bottomLeftY:0,topRightX:t*l,topRightY:i*l},r.pageContext.artBox={bottomLeftX:d(c+s.left)*l,bottomLeftY:d(c+s.bottom)*l,topRightX:d(n-c-s.right)*l,topRightY:d(a-c-s.top)*l},r.pageContext.bleedBox={bottomLeftX:d(c+s.left)*l,bottomLeftY:d(c+s.bottom)*l,topRightX:d(n-c-s.right)*l,topRightY:d(a-c-s.top)*l},p){v.setLineWidth(d(1));const e=p+d(s.left),o=p+d(s.right),n=p+d(s.top),a=p+d(s.bottom);v.line(e,0,e,p),v.line(0,n,p,n),v.line(t-o,0,t-o,p),v.line(t,n,t-p,n),v.line(0,i-a,p,i-a),v.line(e,i,e,i-p),v.line(t,i-a,t-p,i-a),v.line(t-o,i,t-o,i-p)}v.addImage(e,p,p,t-2*p,i-2*p,void 0,"FAST")})}return v},toPDFDataURL:async e=>(await y._toPDF(Object.assign({mimeType:"image/jpeg"},e))).output("datauristring"),async toGIFDataURL(e={}){const t=e.pixelRatio||1,i=e.pageIds||(e.pageId?[e.pageId]:r.pages.map(e=>e.id)),o=r.pages.filter(e=>i.includes(e.id));if(!o.length){throw new Error("No pages found for GIF export")}const n=o[0],a=await h({width:n.computedWidth*t,height:n.computedHeight*t}),s=1e3/(e.fps||10);for(const l of o){const e=Math.max(1,Math.floor(l.duration/s));for(let i=0;i<e;i++){const e=l.startTime+i*s||1;y.setCurrentTime(e);for(const t of r.pages){t.set({_rendering:t.id===l.id})}const o=await y._toCanvas({pixelRatio:t,pageId:l.id,_skipTimeout:!0});a.addFrame(o.getContext("2d"),{delay:s,copy:!0})}}for(const l of r.pages){l.set({_rendering:!1})}return y.stop(),a.render(),new Promise(e=>{a.on("finished",function(t){!function(e,t){var i=new FileReader;i.onload=function(e){t(e.target.result)},i.readAsDataURL(e)}(t,e)})})},async saveAsGIF(t={}){var{fileName:i}=t,o=e(t,["fileName"]);const n=await y.toGIFDataURL(o);u(n,i||"polotno.gif")},async toHTML({elementHook:e}={}){const t=y.toJSON();return k({json:t,elementHook:e})},async saveAsHTML({fileName:e,elementHook:t}={}){const i=await y.toHTML({elementHook:t}),o="data:text/html;base64,"+window.btoa(unescape(encodeURIComponent(i)));u(o,e||"polotno.html")},async toSVG({elementHook:e,pageId:t,fontEmbedding:i="inline"}={fontEmbedding:"inline"}){var o;const n=y.toJSON();t=t||(null===(o=n.pages[0])||void 0===o?void 0:o.id);const a=n.pages.find(e=>e.id===t);return S({json:Object.assign(Object.assign({},n),{pages:a?[a]:[]}),elementHook:e,fontEmbedding:i})},async saveAsSVG({fileName:e,elementHook:t,pageId:i,fontEmbedding:o="inline"}={}){const n=await y.toSVG({elementHook:t,pageId:i,fontEmbedding:o}),a="data:text/svg;base64,"+window.btoa(unescape(encodeURIComponent(n)));u(a,e||"polotno.svg")},async saveAsPDF(t={}){var{fileName:i}=t,o=e(t,["fileName"]);(await y._toPDF(Object.assign({mimeType:"image/jpeg"},o))).save(i||"polotno.pdf")},async waitLoading({_skipTimeout:e=!1}={}){e||await new Promise(e=>setTimeout(e,50)),await x()},toJSON:()=>({width:r.width,height:r.height,fonts:a(r.fonts),pages:a(r.pages),audios:a(r.audios),unit:r.unit,dpi:r.dpi,custom:r.custom,schemaVersion:r.schemaVersion}),loadJSON(e,i=!1){var o,n,s;const l="boolean"==typeof i?i:null!==(o=null==i?void 0:i.keepHistory)&&void 0!==o&&o,d="boolean"!=typeof i&&null!==(n=null==i?void 0:i.modernizeTextBackground)&&void 0!==n&&n,c=JSON.parse(JSON.stringify(e)),p=c.schemaVersion||0;p<1&&(P.htmlRenderEnabled||P.renderTagTextEnabled)&&R({children:c.pages},e=>{if("text"===e.type){const t=16,i=e.letterSpacing*t;e.letterSpacing=i/e.fontSize}}),p<2&&R({children:c.pages},e=>{e.filters&&Object.keys(e.filters).forEach(t=>{if(["warm","cold","natural"].includes(t)){return}const i=e.filters[t];i&&"number"==typeof i.intensity&&(i.intensity=i.intensity/100)})}),p<3&&(P.htmlRenderEnabled||P.renderTagTextEnabled)&&!d&&R({children:c.pages},e=>{"text"===e.type&&e.backgroundEnabled&&(e.legacyBackground=!0)}),delete c.schemaVersion;const g=r.activePage?r.pages.indexOf(r.activePage):0;let m=null===(s=c.pages[g]||c.pages[0])||void 0===s?void 0:s.id;c._activePageId=m;const u=Object.assign({},a(r));Object.assign(u,c),u.history=l?a(r.history):{history:[],undoIdx:-1,targetPath:""},t(r,u)},clear({keepHistory:e=!1}={}){const t=r.pages.map(e=>e.id);y.deletePages(t),r.custom=null,e||r.history.clear()},addFont(e){y.removeFont(e.fontFamily),r.fonts.push(e)},removeFont(e){r.fonts.filter(t=>t.fontFamily===e).forEach(e=>o(e))},addAudio(e){const t=F.create(Object.assign({id:c(10)},e));r.audios.push(t)},removeAudio(e){const t=r.audios.find(t=>t.id===e);t&&r.audios.remove(t)},async loadFont(e,t,i,o){const n=r.fonts.find(t=>t.fontFamily===e)||v.globalFonts.find(t=>t.fontFamily===e);let a=[{fontStyle:"normal",fontWeight:"normal"},{fontStyle:"normal",fontWeight:"bold"}];return n?(n.styles&&(a=n.styles.map(e=>({fontStyle:e.fontStyle||"normal",fontWeight:e.fontWeight||"normal"}))),v.injectCustomFont(n)):v.injectGoogleFont(e),t&&i&&!a.some(e=>e.fontStyle===t&&e.fontWeight===i)&&a.push({fontStyle:t,fontWeight:i}),Promise.all(a.map(t=>v.loadFont(e,t.fontStyle,t.fontWeight,o)))},validate:e=>Store.validate(e,[{path:"",type:Store}]).map(e=>({path:"store"+e.context.map(e=>e.path).join("."),message:e.message}))};return y});export function createStore({key:e,showCredit:t}={key:"",showCredit:!1}){return y(e),Store.create({_forceShowCredit:t})}export default createStore;
@@ -144,6 +144,11 @@ export declare const SVGElement: import("mobx-state-tree").IModelType<{
144
144
  readonly locked: boolean;
145
145
  readonly a: import("./shape-model.js").AnimatedAttrs;
146
146
  animated(attr: any): any;
147
+ readonly timeRange: {
148
+ start: number;
149
+ end: number;
150
+ };
151
+ readonly active: boolean;
147
152
  readonly isSelected: boolean;
148
153
  readonly isSelectedDirectly: boolean;
149
154
  } & {
@@ -428,6 +428,11 @@ export declare const TableElement: import("mobx-state-tree").IModelType<{
428
428
  readonly locked: boolean;
429
429
  readonly a: import("./shape-model.js").AnimatedAttrs;
430
430
  animated(attr: any): any;
431
+ readonly timeRange: {
432
+ start: number;
433
+ end: number;
434
+ };
435
+ readonly active: boolean;
431
436
  readonly isSelected: boolean;
432
437
  readonly isSelectedDirectly: boolean;
433
438
  } & {
@@ -154,6 +154,11 @@ export declare const TextElement: import("mobx-state-tree").IModelType<{
154
154
  readonly locked: boolean;
155
155
  readonly a: import("./shape-model.js").AnimatedAttrs;
156
156
  animated(attr: any): any;
157
+ readonly timeRange: {
158
+ start: number;
159
+ end: number;
160
+ };
161
+ readonly active: boolean;
157
162
  readonly isSelected: boolean;
158
163
  readonly isSelectedDirectly: boolean;
159
164
  } & {
@@ -150,6 +150,11 @@ export declare const VideoElement: import("mobx-state-tree").IModelType<{
150
150
  readonly locked: boolean;
151
151
  readonly a: import("./shape-model.js").AnimatedAttrs;
152
152
  animated(attr: any): any;
153
+ readonly timeRange: {
154
+ start: number;
155
+ end: number;
156
+ };
157
+ readonly active: boolean;
153
158
  readonly isSelected: boolean;
154
159
  readonly isSelectedDirectly: boolean;
155
160
  } & {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "polotno",
3
- "version": "4.1.3",
3
+ "version": "4.2.1",
4
4
  "description": "Design Editor Framework",
5
5
  "author": "Anton Lavrenov",
6
6
  "keywords": [
@@ -78,6 +78,7 @@
78
78
  "./ui.css": "./ui.css",
79
79
  "./fonts.css": "./fonts.css",
80
80
  "./themes/blueprint.css": "./themes/blueprint.css",
81
+ "./themes/carbon.css": "./themes/carbon.css",
81
82
  "./blueprint/toolbar": {
82
83
  "import": "./blueprint/toolbar/toolbar.js",
83
84
  "types": "./blueprint/toolbar/toolbar.d.ts"
@@ -95,7 +96,7 @@
95
96
  },
96
97
  "dependencies": {
97
98
  "@base-ui/react": "^1.5.0",
98
- "@polotno/schema": "0.1.4",
99
+ "@polotno/schema": "0.1.5",
99
100
  "class-variance-authority": "^0.7.1",
100
101
  "clsx": "^2.1.1",
101
102
  "gifuct-js": "^2.1.2",
@@ -114,7 +115,7 @@
114
115
  "react-konva-utils": "^2.0.0",
115
116
  "react-sortablejs": "6.1.4",
116
117
  "react-window": "^1.8.11",
117
- "render-tag": "^0.1.15",
118
+ "render-tag": "^0.1.16",
118
119
  "sortablejs": "^1.15.7",
119
120
  "svg-round-corners": "^0.4.3",
120
121
  "swr": "^2.4.1",
@@ -220,7 +221,7 @@
220
221
  "check:parity": "node build/structural-parity.cjs",
221
222
  "test:parity": "pnpm run check:parity && pnpm run check:agreement && pnpm run check:css",
222
223
  "minify": "node minify.cjs",
223
- "build": "pnpm run typecheck && pnpm run clean && pnpm run prefix-build && pnpm run tsc && pnpm run add_version && node rename-imports.js && pnpm run minify && pnpm run build:css && pnpm run check:css && pnpm run check:agreement && pnpm run build:bundle && node blueprint-scope.js && cp ./src/fonts.css ./lib/fonts.css && mkdir -p ./lib/themes && cp ./src/themes/blueprint.css ./lib/themes/blueprint.css && node build/copy-package-json.cjs && cp ./README.md ./lib && cp ./LICENSE.md ./lib && pnpm run remove-test-from-lib",
224
+ "build": "pnpm run typecheck && pnpm run clean && pnpm run prefix-build && pnpm run tsc && pnpm run add_version && node rename-imports.js && pnpm run minify && pnpm run build:css && pnpm run check:css && pnpm run check:agreement && pnpm run build:bundle && node blueprint-scope.js && cp ./src/fonts.css ./lib/fonts.css && mkdir -p ./lib/themes && cp ./src/themes/blueprint.css ./lib/themes/blueprint.css && cp ./src/themes/carbon.css ./lib/themes/carbon.css && node build/copy-package-json.cjs && cp ./README.md ./lib && cp ./LICENSE.md ./lib && pnpm run remove-test-from-lib",
224
225
  "remove-test-from-lib": "find ./lib -type d -name \"__tests__\" -exec rm -rf {} + && find ./lib \\( -name \"*.test.js\" -o -name \"*.test.d.ts\" \\) -type f -delete",
225
226
  "add_version": "sed -i.bak 's/SDK_VERSION/'$npm_package_version'/' ./lib/utils/validate-key.js && rm -f ./lib/utils/validate-key.js.bak",
226
227
  "build:bundle": "vite build && find ./lib -name '*.js.map' -type f -delete",
@@ -1 +1 @@
1
- import{jsx as e,jsxs as t}from"react/jsx-runtime";import n from"react";import{observer as o}from"mobx-react-lite";const r="rgb(0, 161, 255)";export const CurrentTime=o(({store:o,scale:i,variant:a="timeline",dragAreaRef:s})=>{var l;const c=n.useRef(null),u=(null===(l=o.activePage)||void 0===l?void 0:l.startTime)||0,d=o.isPlaying||0!==o.currentTime?o.currentTime:u,v=n.useCallback(e=>Math.max(0,Math.min(e,o.duration)),[o.duration]),p=n.useCallback(e=>{var t,n;const r=(null==s?void 0:s.current)||(null===(t=c.current)||void 0===t?void 0:t.parentElement);if(!r){return}const a=r.getBoundingClientRect(),l=r.scrollLeft||0;let u=e-a.left+l;const d=window.getComputedStyle(r);u-=parseFloat(d.paddingLeft)||0;const p=Math.max(0,u),m=v(p/i);o.setCurrentTime(m),null===(n=o.checkActivePage)||void 0===n||n.call(o)},[v,s,i,o]),m=n.useCallback(e=>{p(e);const t=e=>{e.preventDefault(),p(e.clientX)},n=()=>{window.removeEventListener("mousemove",t),window.removeEventListener("mouseup",n)};window.addEventListener("mousemove",t),window.addEventListener("mouseup",n)},[p]),w=n.useCallback(e=>{p(e);const t=e=>{const t=e.touches[0];t&&(e.preventDefault(),p(t.clientX))},n=()=>{window.removeEventListener("touchmove",t),window.removeEventListener("touchend",n),window.removeEventListener("touchcancel",n)};window.addEventListener("touchmove",t,{passive:!1}),window.addEventListener("touchend",n),window.addEventListener("touchcancel",n)},[p]),h=n.useCallback(e=>{e.preventDefault(),e.stopPropagation(),m(e.clientX)},[m]),g=n.useCallback(e=>{const t=e.touches[0];t&&(e.preventDefault(),e.stopPropagation(),w(t.clientX))},[w]),f=(e=>"ruler"===e?{wrapper:{top:0,width:12,height:"100%",transform:"translateX(-6px)",display:"flex",flexDirection:"column",alignItems:"center"},line:{flex:1}}:{wrapper:{top:0,width:12,height:"100%",transform:"translateX(-6px)"},line:{height:"100%",margin:"0 auto"}})(a);return t("div",{ref:c,onMouseDown:h,onTouchStart:g,style:Object.assign(Object.assign({position:"absolute",left:d*i+"px"},f.wrapper),{cursor:"col-resize",touchAction:"none"}),children:[e("svg",{width:"12",height:"8",viewBox:"0 0 12 8",style:{display:"block",filter:"drop-shadow(0 1px 2px rgba(0, 0, 0, 0.3))"},children:e("path",{d:"M0 0 H12 L6 8 Z",fill:r,stroke:r,strokeWidth:"2",strokeLinejoin:"round"})}),e("div",{style:Object.assign({width:"2px",backgroundColor:r},f.line)})]})});
1
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import n from"react";import{observer as o}from"mobx-react-lite";const r="rgb(0, 161, 255)";export const CurrentTime=o(({store:o,scale:i,variant:a="timeline",dragAreaRef:s})=>{const l=n.useRef(null),c=o.effectiveTime,d=n.useCallback(e=>Math.max(0,Math.min(e,o.duration)),[o.duration]),u=n.useCallback(e=>{var t,n;const r=(null==s?void 0:s.current)||(null===(t=l.current)||void 0===t?void 0:t.parentElement);if(!r){return}const a=r.getBoundingClientRect(),c=r.scrollLeft||0;let u=e-a.left+c;const p=window.getComputedStyle(r);u-=parseFloat(p.paddingLeft)||0;const v=Math.max(0,u),m=d(v/i);o.setCurrentTime(m),null===(n=o.checkActivePage)||void 0===n||n.call(o)},[d,s,i,o]),p=n.useCallback(e=>{u(e);const t=e=>{e.preventDefault(),u(e.clientX)},n=()=>{window.removeEventListener("mousemove",t),window.removeEventListener("mouseup",n)};window.addEventListener("mousemove",t),window.addEventListener("mouseup",n)},[u]),v=n.useCallback(e=>{u(e);const t=e=>{const t=e.touches[0];t&&(e.preventDefault(),u(t.clientX))},n=()=>{window.removeEventListener("touchmove",t),window.removeEventListener("touchend",n),window.removeEventListener("touchcancel",n)};window.addEventListener("touchmove",t,{passive:!1}),window.addEventListener("touchend",n),window.addEventListener("touchcancel",n)},[u]),m=n.useCallback(e=>{e.preventDefault(),e.stopPropagation(),p(e.clientX)},[p]),w=n.useCallback(e=>{const t=e.touches[0];t&&(e.preventDefault(),e.stopPropagation(),v(t.clientX))},[v]),h=(e=>"ruler"===e?{wrapper:{top:0,width:12,height:"100%",transform:"translateX(-6px)",display:"flex",flexDirection:"column",alignItems:"center"},line:{flex:1}}:{wrapper:{top:0,width:12,height:"100%",transform:"translateX(-6px)"},line:{height:"100%",margin:"0 auto"}})(a);return t("div",{ref:l,onMouseDown:m,onTouchStart:w,style:Object.assign(Object.assign({position:"absolute",left:c*i+"px"},h.wrapper),{cursor:"col-resize",touchAction:"none"}),children:[e("svg",{width:"12",height:"8",viewBox:"0 0 12 8",style:{display:"block",filter:"drop-shadow(0 1px 2px rgba(0, 0, 0, 0.3))"},children:e("path",{d:"M0 0 H12 L6 8 Z",fill:r,stroke:r,strokeWidth:"2",strokeLinejoin:"round"})}),e("div",{style:Object.assign({width:"2px",backgroundColor:r},h.line)})]})});
@@ -1 +1 @@
1
- import{jsx as e,jsxs as t}from"react/jsx-runtime";import n from"react";import{observer as o}from"mobx-react-lite";import{PolotnoIcon as i}from"../icons/registry.js";import{duplicateElements as r}from"../utils/duplicate.js";import{t as s}from"../utils/l10n.js";import{DropdownMenu as a,DropdownMenuContent as l,DropdownMenuItem as m}from"../primitives/dropdown-menu.js";import{TrackWrapper as d,TrackContainer as p,TrackMenu as c,TrackMenuButton as u,TrackHandleLeft as v,TrackHandleRight as w,TrackLabel as f}from"./track-styles.js";export const ELEMENT_ROW_HEIGHT=26;const x=100,h=(e,t,n)=>Math.min(n,Math.max(t,e)),E=(e,t)=>{const n=e.animations.find(e=>e.type===t);n?n.enabled||e.setAnimation(t,{enabled:!0}):e.setAnimation(t,{})},y=(e,t,n,o)=>{const i=h(n,0,t-x),r=h(o,i+x,t);E(e,"enter"),E(e,"exit"),e.setAnimation("enter",{delay:i}),e.setAnimation("exit",{delay:Math.max(0,t-r)})};export const ElementTrack=o(({element:o,page:E,store:M,scale:D,row:L})=>{const g=E.duration,j=E.startTime,b=j+g,A=h((e=>{var t;const n=e.animations.find(e=>"enter"===e.type);return null!==(t=null==n?void 0:n.delay)&&void 0!==t?t:0})(o),0,g),P=h(g-(e=>{var t;const n=e.animations.find(e=>"exit"===e.type);return null!==(t=null==n?void 0:n.delay)&&void 0!==t?t:0})(o),A+x,g),T=Math.max(P-A,x)*D,X=(j+A)*D,k=o.name||o.type||s("toolbar.element"),[S,H]=n.useState(null),N=()=>{H(e=>null===e?L:e)},O=()=>{H(null)},$=(e,t)=>{e.preventDefault(),e.stopPropagation(),N();const n=e.clientX,i=A,r=P,s=e=>{e.preventDefault();const s=(e.clientX-n)/D;if("start"===t){const e=h(j+i+s,j,j+r-x);y(o,g,e-j,r)}else{const e=h(j+r+s,j+i+x,b);y(o,g,i,e-j)}},a=()=>{window.removeEventListener("mousemove",s),window.removeEventListener("mouseup",a),O()};window.addEventListener("mousemove",s),window.addEventListener("mouseup",a)};return e(d,{style:{left:`${X}px`,top:26*(null!=S?S:L)+"px",width:`${T}px`,height:"22px"},children:t(p,{style:{width:"100%",height:"100%",outline:M.selectedElements.find(e=>e.id===o.id)?"2px solid var(--pn-primary, var(--primary, #137cbd))":"none",outlineOffset:"-1px"},onMouseDown:e=>{e.preventDefault(),e.stopPropagation(),N();const t=e.clientX,n=A,i=P-n;let r=!1;const s=e=>{e.preventDefault(),r=!0;const s=(e.clientX-t)/D,a=h(j+n+s,j,b-i)-j;y(o,g,a,a+i)},a=()=>{window.removeEventListener("mousemove",s),window.removeEventListener("mouseup",a),O(),r||M.selectElements([o.id])};window.addEventListener("mousemove",s),window.addEventListener("mouseup",a)},children:[e(f,{children:k}),e(v,{onMouseDown:e=>$(e,"start")}),e(w,{onMouseDown:e=>$(e,"end")}),e(c,{onMouseDown:e=>e.stopPropagation(),onClick:e=>e.stopPropagation(),children:t(a,{children:[e(u,{}),t(l,{side:"top",className:"pn:whitespace-nowrap",children:[t(m,{onSelect:e=>{e.preventDefault(),r([o],M)},children:[e(i,{name:"action.duplicate"}),s("contextMenu.duplicate")]}),t(m,{onSelect:e=>{e.preventDefault(),M.deleteElements([o.id])},children:[e(i,{name:"action.remove"}),s("contextMenu.remove")]})]})]})})]})})});
1
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import n from"react";import{observer as o}from"mobx-react-lite";import{PolotnoIcon as i}from"../icons/registry.js";import{duplicateElements as s}from"../utils/duplicate.js";import{clamp as r}from"../lib/utils.js";import{getElementTimeRange as l,MIN_DURATION as m,revealElementAtPlayhead as a}from"../utils/timeline.js";import{canSplitAtPlayhead as p,splitElementAtPlayhead as d}from"../utils/split-element.js";import{t as c}from"../utils/l10n.js";import{DropdownMenu as u,DropdownMenuContent as v,DropdownMenuItem as f}from"../primitives/dropdown-menu.js";import{TrackWrapper as w,TrackContainer as x,TrackMenu as h,TrackMenuButton as E,TrackHandleLeft as j,TrackHandleRight as D,TrackLabel as y}from"./track-styles.js";export const ELEMENT_ROW_HEIGHT=26;const g=o(({element:n,store:o})=>{var s;const r=o.effectiveTime-((null===(s=n.page)||void 0===s?void 0:s.startTime)||0),l=p(n,r);return t(f,{disabled:!l,onSelect:e=>{e.preventDefault();const t=d(n,r);t&&o.selectElements([t.id])},children:[e(i,{name:"action.split"}),c("contextMenu.split")]})}),L=(e,t)=>{const n=e.animations.find(e=>e.type===t);n&&n.enabled||e.setAnimation(t,{name:"none",enabled:!0})},M=(e,t,n,o)=>{const i=r(n,0,t-m),s=r(o,i+m,t);L(e,"enter"),L(e,"exit"),e.setAnimation("enter",{delay:i}),e.setAnimation("exit",{delay:Math.max(0,t-s)})};export const ElementTrack=o(({element:o,page:p,store:d,scale:L,row:b})=>{const T=p.duration,P=p.startTime,S=P+T,{start:X,end:k}=l(o.animations,T),A=(k-X)*L,H=(P+X)*L,N=o.name||o.type||c("toolbar.element"),[O,W]=n.useState(null),$=()=>{W(e=>null===e?b:e)},_=()=>{W(null)},C=(e,t)=>{e.preventDefault(),e.stopPropagation(),$();const n=e.clientX,i=X,s=k,l=e=>{e.preventDefault();const l=(e.clientX-n)/L;if("start"===t){const e=r(P+i+l,P,P+s-m);M(o,T,e-P,s)}else{const e=r(P+s+l,P+i+m,S);M(o,T,i,e-P)}},a=()=>{window.removeEventListener("mousemove",l),window.removeEventListener("mouseup",a),_()};window.addEventListener("mousemove",l),window.addEventListener("mouseup",a)};return e(w,{style:{left:`${H}px`,top:26*(null!=O?O:b)+"px",width:`${A}px`,minWidth:"6px",height:"22px"},children:t(x,{style:{width:"100%",height:"100%",outline:d.selectedElements.find(e=>e.id===o.id)?"2px solid var(--pn-primary, var(--primary, #137cbd))":"none",outlineOffset:"-1px"},onMouseDown:e=>{e.preventDefault(),e.stopPropagation(),$();const t=e.clientX,n=X,i=k-n;let s=!1;const l=e=>{e.preventDefault(),s=!0;const l=(e.clientX-t)/L,m=r(P+n+l,P,S-i)-P;M(o,T,m,m+i)},m=()=>{window.removeEventListener("mousemove",l),window.removeEventListener("mouseup",m),_(),s||(d.selectElements([o.id]),a(o))};window.addEventListener("mousemove",l),window.addEventListener("mouseup",m)},children:[e(y,{children:N}),e(j,{onMouseDown:e=>C(e,"start")}),e(D,{onMouseDown:e=>C(e,"end")}),e(h,{onMouseDown:e=>e.stopPropagation(),onClick:e=>e.stopPropagation(),children:t(u,{children:[e(E,{}),t(v,{side:"top",className:"pn:whitespace-nowrap",children:[e(g,{element:o,store:d}),t(f,{onSelect:e=>{e.preventDefault(),s([o],d)},children:[e(i,{name:"action.duplicate"}),c("contextMenu.duplicate")]}),t(f,{onSelect:e=>{e.preventDefault(),d.deleteElements([o.id])},children:[e(i,{name:"action.remove"}),c("contextMenu.remove")]})]})]})})]})})});
@@ -1 +1 @@
1
- import{jsx as e}from"react/jsx-runtime";import{observer as t}from"mobx-react-lite";import{forEveryChild as n}from"../model/group-model.js";import{packRows as r}from"../utils/pack-rows.js";import{ElementTrack as a,ELEMENT_ROW_HEIGHT as o}from"./element-track.js";export const ElementsTimeline=t(({store:t,scale:l,width:i})=>{const s=t.pages.slice();if(!s.length){return null}const m=s.flatMap(e=>(e=>{const t=[];for(const r of e.children){"group"===r.type?n(r,e=>{"group"!==e.type&&t.push(e)}):t.push(r)}return t})(e).map(t=>({element:t,page:e}))).filter(({element:e})=>e.selectable||"admin"===t.role);if(!m.length){return null}const p=(e=>{const t=e.map(({element:e,page:t})=>{const n=((e,t)=>{var n,r;const a=t.duration,o=e.animations.find(e=>"enter"===e.type),l=e.animations.find(e=>"exit"===e.type),i=Math.max(0,Math.min(a,null!==(n=null==o?void 0:o.delay)&&void 0!==n?n:0));return{start:i,end:Math.max(i+50,Math.min(a,a-(null!==(r=null==l?void 0:l.delay)&&void 0!==r?r:0)))}})(e,t);return{element:e,page:t,start:t.startTime+n.start,end:t.startTime+n.end}}).sort((e,t)=>e.start-t.start).filter(e=>e.end-e.start>=50);return r(t.map(e=>({item:e,start:e.start,end:e.end}))).map(({item:e,row:t})=>({element:e.element,page:e.page,row:t,start:e.start,end:e.end}))})(m);if(!p.length){return null}const d=p.reduce((e,t)=>Math.max(e,t.row),-1)+1;return e("div",{style:{position:"relative",minWidth:i+"px",height:d*o+"px",marginTop:"12px"},className:"polotno-elements-container",children:p.map(({element:n,row:r,page:o})=>e(a,{element:n,store:t,page:o,scale:l,row:r},`${o.id}-${n.id}`))})});
1
+ import{jsx as e}from"react/jsx-runtime";import{observer as t}from"mobx-react-lite";import{forEveryChild as r}from"../model/group-model.js";import{packRows as n}from"../utils/pack-rows.js";import{getElementTimeRange as o}from"../utils/timeline.js";import{ElementTrack as s,ELEMENT_ROW_HEIGHT as a}from"./element-track.js";export const ElementsTimeline=t(({store:t,scale:m,width:i})=>{const l=t.pages.slice();if(!l.length){return null}const p=l.flatMap(e=>(e=>{const t=[];for(const n of e.children){"group"===n.type?r(n,e=>{"group"!==e.type&&t.push(e)}):t.push(n)}return t})(e).map(t=>({element:t,page:e}))).filter(({element:e})=>e.selectable||"admin"===t.role);if(!p.length){return null}const c=(e=>{const t=e.map(({element:e,page:t})=>{const r=o(e.animations,t.duration);return{element:e,page:t,start:t.startTime+r.start,end:t.startTime+r.end}}).sort((e,t)=>e.start-t.start).filter(e=>e.end>e.start);return n(t.map(e=>({item:e,start:e.start,end:e.end}))).map(({item:e,row:t})=>({element:e.element,page:e.page,row:t,start:e.start,end:e.end}))})(p);if(!c.length){return null}const u=c.reduce((e,t)=>Math.max(e,t.row),-1)+1;return e("div",{style:{position:"relative",minWidth:i+"px",height:u*a+"px",marginTop:"12px"},className:"polotno-elements-container",children:c.map(({element:r,row:n,page:o})=>e(s,{element:r,store:t,page:o,scale:m,row:n},`${o.id}-${r.id}`))})});
@@ -1 +1 @@
1
- import{jsx as e,jsxs as t}from"react/jsx-runtime";import o from"react";import{observer as n}from"mobx-react-lite";import{reaction as i}from"mobx";import{onSnapshot as s}from"mobx-state-tree";import{PolotnoIcon as a}from"../icons/registry.js";import{flags as r}from"../utils/flags.js";import{t as l}from"../utils/l10n.js";import{deepEqual as d}from"../utils/deep-equal.js";import{DropdownMenu as c,DropdownMenuContent as p,DropdownMenuItem as u}from"../primitives/dropdown-menu.js";import{Spinner as g}from"./spinner.js";import{TrackMenuButton as m}from"./track-styles.js";let h=[],f=!1;const v=async()=>{if(f||0===h.length){return}f=!0;const{page:e,setPreview:t}=h.shift();try{t(await e.store.toDataURL({pageId:e.id,pixelRatio:.1,quickMode:!0}))}catch(o){o instanceof Error&&"string"==typeof o.message&&(o.message.includes("Canvas was unmounted.")||o.message.includes("<Workspace /> component is not mounted"))||console.error(o)}finally{f=!1}v()};export const usePagePreview=({page:e,setPreview:t,groupRef:n})=>{const a=o.useRef(!1);o.useEffect(()=>{const o=()=>{h.push({page:e,setPreview:e=>t(e)}),v()};let r=null,l=null,c=Date.now();const p=()=>{r&&clearTimeout(r),a.current&&(l||(l=setTimeout(()=>{Date.now()-c>=6e3&&(o(),c=Date.now(),l=null)},6e3)),r=setTimeout(()=>{o(),c=Date.now(),r=null,l&&(clearTimeout(l),l=null)},300))};let u=null;const g=s(e,e=>{d(u,e)||(p(),u=e)}),m=i(()=>e.children.some(e=>e._editModeEnabled),e=>{e||p()}),f=new IntersectionObserver(e=>{e.forEach(e=>{e.isIntersecting?(a.current=!0,p()):(r&&clearTimeout(r),l&&clearTimeout(l),a.current=!1)})},{threshold:.1});return n.current&&f.observe(n.current),()=>{f.disconnect(),r&&clearTimeout(r),l&&clearTimeout(l),g(),m(),h=h.filter(t=>t.page!==e)}},[n,e,t])};export const PagePreview=n(({page:n,scale:i})=>{const[s,d]=o.useState(null),[h,f]=o.useState(!1),v=n.store.activePage===n||n.store._selectedPagesIds.includes(n.id),x=o.useRef(null),b=n.store.pages.indexOf(n),w=60/n.computedHeight*n.computedWidth,P=r.animationsEnabled?n.duration*i:w,y=n.store.pages.length>1;o.useLayoutEffect(()=>{x.current&&(x.current.style.width=P+"px")},[b,P]),usePagePreview({page:n,setPreview:d,groupRef:x});const{handleStartDrag:E}=((e,t)=>({handleStartDrag:o.useCallback((o,n)=>{o.preventDefault();const i=o=>{if(o.preventDefault(),!t.current){return}const i="start"===n?7:-7,{clientX:s}=o,{left:a,width:r}=t.current.getBoundingClientRect(),l=(s-a-i)/r;"end"===n&&e.set({duration:Math.max(1e3,l*e.duration)})},s=()=>{window.removeEventListener("mousemove",i),window.removeEventListener("mouseup",s)};window.addEventListener("mousemove",i),window.addEventListener("mouseup",s)},[t,e])}))(n,x);return t("div",{ref:x,style:{width:P+"px",marginRight:r.animationsEnabled?"0px":"10px",height:"60px",display:"flex",position:"relative",borderRadius:"15px"},onMouseEnter:()=>f(!0),onMouseLeave:()=>f(!1),className:"polotno-page-container"+(v?" sortable-selected":""),children:[e("div",{style:{width:"100%",height:"100%",borderRadius:"15px",backgroundImage:s?`url("${s}")`:"none",backgroundRepeat:"repeat-x",backgroundSize:"auto 100%",backgroundColor:"white",display:"flex",justifyContent:"center",alignItems:"center"},onClick:e=>{const{store:t}=n,o=t._selectedPagesIds.length?t._selectedPagesIds:t.activePage?[t.activePage.id]:[],i=o.includes(n.id),s=e.shiftKey;if(s&&i){const e=o.filter(e=>e!==n.id);t.selectPages(e)}else if(s&&!i){const e=o.concat([n.id]);t.selectPages(e)}else{t.selectPages([n.id])}},children:!s&&e(g,{})}),e("div",{style:{position:"absolute",top:"0",left:"0px",bottom:"0px",right:"0px",borderRadius:"15px",border:v?"2px solid rgb(0, 161, 255, 0.9)":"2px solid var(--pn-border)",zIndex:1,pointerEvents:"none"}}),r.animationsEnabled&&t("div",{style:{position:"absolute",zIndex:1,bottom:"5px",left:"5px",backgroundColor:"rgba(0, 0, 0, 0.5)",color:"white",padding:"2px 7px",textAlign:"center",borderRadius:"4rem"},children:[(n.duration/1e3).toFixed(1),"s"]}),r.animationsEnabled&&e("div",{style:{position:"absolute",zIndex:1,top:"50%",right:"0px",width:"8px",height:"50%",transform:"translateY(-50%) translateX(-3px)",borderRadius:"5px",border:"1px solid rgb(255, 255, 255, 0.6)",backgroundColor:"rgb(0, 0, 0, 0.6)",cursor:"ew-resize"},onMouseDown:e=>E(e,"end")}),v&&e("div",{className:"polotno-page-menu",style:{position:"absolute",zIndex:20,top:"5px",right:"5px",opacity:h?1:0,pointerEvents:h?"auto":"none",transition:"opacity 0.15s"},onClick:e=>{e.stopPropagation()},children:t(c,{children:[e(m,{}),t(p,{side:"top",className:"pn:whitespace-nowrap",children:[t(u,{onSelect:e=>{e.preventDefault();const t=n.store,o=(t.selectedPages||[]).filter(Boolean),i=o.length?o:t.activePage?[t.activePage]:[];if(!i.length){return}const s=new Set(i.map(e=>e.id)),a=t.pages.filter(e=>s.has(e.id)),r=a[a.length-1],l=a.map(e=>e.clone()),d=t.pages.indexOf(r);l.forEach((e,t)=>{e.setZIndex(d+1+t)}),t.selectPages(l.map(e=>e.id))},children:[e(a,{name:"action.duplicate",className:"pn:size-4"}),l("pagesTimeline.duplicatePage")]}),t(u,{onSelect:e=>{var t,o,i;e.preventDefault();const s=n.store.addPage({bleed:(null===(t=n.store.activePage)||void 0===t?void 0:t.bleed)||0,width:(null===(o=n.store.activePage)||void 0===o?void 0:o.width)||"auto",height:(null===(i=n.store.activePage)||void 0===i?void 0:i.height)||"auto"}),a=n.store.pages.indexOf(n);s.setZIndex(a+1)},children:[e(a,{name:"action.add",className:"pn:size-4"}),l("pagesTimeline.addPage")]}),y&&t(u,{onSelect:e=>{e.preventDefault();const t=n.store,o=(t.selectedPages||[]).filter(Boolean),i=o.length?o.map(e=>e.id):t.activePage?[t.activePage.id]:[];i.length&&t.deletePages(i)},children:[e(a,{name:"action.remove",className:"pn:size-4"}),l("pagesTimeline.removePage")]})]})]})})]})});
1
+ import{jsx as e,jsxs as t}from"react/jsx-runtime";import o from"react";import{observer as n}from"mobx-react-lite";import{reaction as i}from"mobx";import{onSnapshot as s}from"mobx-state-tree";import{PolotnoIcon as a}from"../icons/registry.js";import{flags as r}from"../utils/flags.js";import{t as l}from"../utils/l10n.js";import{deepEqual as d}from"../utils/deep-equal.js";import{DropdownMenu as c,DropdownMenuContent as p,DropdownMenuItem as u}from"../primitives/dropdown-menu.js";import{Spinner as g}from"./spinner.js";import{TrackMenuButton as m}from"./track-styles.js";let h=[],f=!1;const v=async()=>{if(f||0===h.length){return}f=!0;const{page:e,setPreview:t}=h.shift();try{t(await e.store.toDataURL({pageId:e.id,pixelRatio:.1,quickMode:!0}))}catch(o){o instanceof Error&&"string"==typeof o.message&&(o.message.includes("Canvas was unmounted.")||o.message.includes("<Workspace /> component is not mounted"))||console.error(o)}finally{f=!1}v()};export const usePagePreview=({page:e,setPreview:t,groupRef:n})=>{const a=o.useRef(!1);o.useEffect(()=>{const o=()=>{h.push({page:e,setPreview:e=>t(e)}),v()};let r=null,l=null,c=Date.now();const p=()=>{r&&clearTimeout(r),a.current&&(l||(l=setTimeout(()=>{Date.now()-c>=6e3&&(o(),c=Date.now(),l=null)},6e3)),r=setTimeout(()=>{o(),c=Date.now(),r=null,l&&(clearTimeout(l),l=null)},300))};let u=null;const g=s(e,e=>{d(u,e)||(p(),u=e)}),m=i(()=>e.children.some(e=>e._editModeEnabled),e=>{e||p()}),f=new IntersectionObserver(e=>{e.forEach(e=>{e.isIntersecting?(a.current=!0,p()):(r&&clearTimeout(r),l&&clearTimeout(l),a.current=!1)})},{threshold:.1});return n.current&&f.observe(n.current),()=>{f.disconnect(),r&&clearTimeout(r),l&&clearTimeout(l),g(),m(),h=h.filter(t=>t.page!==e)}},[n,e,t])};export const PagePreview=n(({page:n,scale:i})=>{const[s,d]=o.useState(null),[h,f]=o.useState(!1),v=n.store.activePage===n||n.store._selectedPagesIds.includes(n.id),x=o.useRef(null),b=n.store.pages.indexOf(n),w=60/n.computedHeight*n.computedWidth,P=r.animationsEnabled?n.duration*i:w,y=n.store.pages.length>1;o.useLayoutEffect(()=>{x.current&&(x.current.style.width=P+"px")},[b,P]),usePagePreview({page:n,setPreview:d,groupRef:x});const{handleStartDrag:E}=((e,t)=>({handleStartDrag:o.useCallback((o,n)=>{o.preventDefault();const i=o=>{if(o.preventDefault(),!t.current){return}const i="start"===n?7:-7,{clientX:s}=o,{left:a,width:r}=t.current.getBoundingClientRect(),l=(s-a-i)/r;"end"===n&&e.set({duration:Math.max(1e3,l*e.duration)})},s=()=>{window.removeEventListener("mousemove",i),window.removeEventListener("mouseup",s)};window.addEventListener("mousemove",i),window.addEventListener("mouseup",s)},[t,e])}))(n,x);return t("div",{ref:x,style:{width:P+"px",marginRight:r.animationsEnabled?"0px":"10px",height:"60px",display:"flex",position:"relative",borderRadius:"15px",boxShadow:"0 1px 4px rgba(0, 0, 0, 0.18)"},onMouseEnter:()=>f(!0),onMouseLeave:()=>f(!1),className:"polotno-page-container"+(v?" sortable-selected":""),children:[e("div",{style:{width:"100%",height:"100%",borderRadius:"15px",backgroundImage:s?`url("${s}")`:"none",backgroundRepeat:"repeat-x",backgroundSize:"auto 100%",backgroundColor:"white",display:"flex",justifyContent:"center",alignItems:"center"},onClick:e=>{const{store:t}=n,o=t._selectedPagesIds.length?t._selectedPagesIds:t.activePage?[t.activePage.id]:[],i=o.includes(n.id),s=e.shiftKey;if(s&&i){const e=o.filter(e=>e!==n.id);t.selectPages(e)}else if(s&&!i){const e=o.concat([n.id]);t.selectPages(e)}else{t.selectPages([n.id])}},children:!s&&e(g,{})}),e("div",{style:{position:"absolute",top:"0",left:"0px",bottom:"0px",right:"0px",borderRadius:"15px",border:v?"2px solid rgb(0, 161, 255, 0.9)":"2px solid var(--pn-border)",zIndex:1,pointerEvents:"none"}}),r.animationsEnabled&&t("div",{style:{position:"absolute",zIndex:1,bottom:"5px",left:"5px",backgroundColor:"rgba(0, 0, 0, 0.5)",color:"white",padding:"2px 7px",textAlign:"center",borderRadius:"4rem"},children:[(n.duration/1e3).toFixed(1),"s"]}),r.animationsEnabled&&e("div",{style:{position:"absolute",zIndex:1,top:"50%",right:"0px",width:"8px",height:"50%",transform:"translateY(-50%) translateX(-3px)",borderRadius:"5px",border:"1px solid rgb(255, 255, 255, 0.6)",backgroundColor:"rgb(0, 0, 0, 0.6)",cursor:"ew-resize"},onMouseDown:e=>E(e,"end")}),v&&e("div",{className:"polotno-page-menu",style:{position:"absolute",zIndex:20,top:"5px",right:"5px",opacity:h?1:0,pointerEvents:h?"auto":"none",transition:"opacity 0.15s"},onClick:e=>{e.stopPropagation()},children:t(c,{children:[e(m,{}),t(p,{side:"top",className:"pn:whitespace-nowrap",children:[t(u,{onSelect:e=>{e.preventDefault();const t=n.store,o=(t.selectedPages||[]).filter(Boolean),i=o.length?o:t.activePage?[t.activePage]:[];if(!i.length){return}const s=new Set(i.map(e=>e.id)),a=t.pages.filter(e=>s.has(e.id)),r=a[a.length-1],l=a.map(e=>e.clone()),d=t.pages.indexOf(r);l.forEach((e,t)=>{e.setZIndex(d+1+t)}),t.selectPages(l.map(e=>e.id))},children:[e(a,{name:"action.duplicate",className:"pn:size-4"}),l("pagesTimeline.duplicatePage")]}),t(u,{onSelect:e=>{var t,o,i;e.preventDefault();const s=n.store.addPage({bleed:(null===(t=n.store.activePage)||void 0===t?void 0:t.bleed)||0,width:(null===(o=n.store.activePage)||void 0===o?void 0:o.width)||"auto",height:(null===(i=n.store.activePage)||void 0===i?void 0:i.height)||"auto"}),a=n.store.pages.indexOf(n);s.setZIndex(a+1)},children:[e(a,{name:"action.add",className:"pn:size-4"}),l("pagesTimeline.addPage")]}),y&&t(u,{onSelect:e=>{e.preventDefault();const t=n.store,o=(t.selectedPages||[]).filter(Boolean),i=o.length?o.map(e=>e.id):t.activePage?[t.activePage.id]:[];i.length&&t.deletePages(i)},children:[e(a,{name:"action.remove",className:"pn:size-4"}),l("pagesTimeline.removePage")]})]})]})})]})});
@@ -1 +1 @@
1
- import{jsxs as e,jsx as i}from"react/jsx-runtime";import{observer as n}from"mobx-react-lite";import{PolotnoIcon as a}from"../icons/registry.js";import{Button as t}from"../primitives/button.js";import{ButtonGroup as s}from"../primitives/button-group.js";const l=e=>{const i=Math.floor(e/6e4),n=Math.floor(e%6e4/1e3);return`${i.toString().padStart(2,"0")}:${n.toString().padStart(2,"0")}`};export const PlayButton=n(({store:n,scale:o,onScaleChange:r})=>{var p;const m=(null===(p=n.activePage)||void 0===p?void 0:p.startTime)||0,c=n.isPlaying||0!==n.currentTime?n.currentTime:m;return e("div",{className:"pn:grid pn:w-full pn:grid-cols-[1fr_auto_1fr] pn:items-center pn:gap-3",children:[i("div",{className:"pn:flex pn:justify-end",children:e("div",{className:"pn:text-[13px] pn:font-medium pn:tabular-nums pn:opacity-[0.85]",children:[l(c)," / ",l(n.duration)]})}),i("div",{className:"polotno-play-button-container pn:inline-flex pn:items-center pn:justify-center pn:gap-2",children:i(t,{variant:"ghost",size:"icon",className:"pn:size-[30px]","aria-label":n.isPlaying?"Pause":"Play",onClick:()=>{var e;if(n.isPlaying){const e=n.activePage;n.stop(),e&&n.selectPage(e.id)}else{n.play({startTime:(null===(e=n.activePage)||void 0===e?void 0:e.startTime)||0})}},children:n.isPlaying?i(a,{name:"pagesTimeline.pause",className:"pn:size-[25px]"}):i(a,{name:"pagesTimeline.play",className:"pn:size-[25px]"})})}),r&&o&&e("div",{className:"pn:flex pn:items-center pn:justify-end pn:gap-1.5",children:[i("div",{className:"pn:text-xs pn:font-medium pn:tabular-nums pn:opacity-60",children:"Zoom timeline"}),e(s,{className:"pn:items-center",children:[i(t,{variant:"ghost",size:"icon-sm",className:"pn:size-[30px]",onClick:()=>{r&&o&&r(Math.max(o/1.5,.005))},title:"Zoom out timeline","aria-label":"Zoom out timeline",children:i("span",{className:"pn:font-bold",children:"−"})}),i(t,{variant:"ghost",size:"icon-sm",className:"pn:size-[30px]",onClick:()=>{r&&o&&r(Math.min(1.5*o,.2))},title:"Zoom in timeline","aria-label":"Zoom in timeline",children:i("span",{className:"pn:font-bold",children:"+"})})]})]})]})});
1
+ import{jsx as e,jsxs as i}from"react/jsx-runtime";import{observer as n}from"mobx-react-lite";import{PolotnoIcon as t}from"../icons/registry.js";import{Button as a}from"../primitives/button.js";import{ButtonGroup as s}from"../primitives/button-group.js";import{Switch as l}from"../primitives/switch.js";import{t as p}from"../utils/l10n.js";const r=e=>{const i=Math.floor(e/6e4),n=Math.floor(e%6e4/1e3);return`${i.toString().padStart(2,"0")}:${n.toString().padStart(2,"0")}`};export const PlayButton=n(({store:n,scale:o,onScaleChange:m})=>{const c=n.effectiveTime;return i("div",{className:"pn:grid pn:w-full pn:grid-cols-[1fr_auto_1fr] pn:items-center pn:gap-3",children:[i("div",{className:"pn:flex pn:items-center pn:justify-between pn:gap-2",children:[i("label",{className:"pn:flex pn:cursor-pointer pn:items-center pn:gap-2 pn:text-xs pn:font-medium pn:select-none",title:p("pagesTimeline.editAsVideoHint"),children:[e(l,{checked:"playhead"===n.timingPreview,onCheckedChange:e=>n.setTimingPreview(e?"playhead":"all")}),p("pagesTimeline.editAsVideo")]}),i("div",{className:"pn:text-[13px] pn:font-medium pn:tabular-nums pn:opacity-[0.85]",children:[r(c)," / ",r(n.duration)]})]}),i("div",{className:"polotno-play-button-container pn:inline-flex pn:items-center pn:justify-center pn:gap-2",children:[e(a,{variant:"ghost",size:"icon",className:"pn:size-[30px]","aria-label":p("pagesTimeline.rewind"),title:p("pagesTimeline.rewind"),onClick:()=>n.stop(),children:e(t,{name:"pagesTimeline.rewind",className:"pn:size-[20px]"})}),e(a,{variant:"ghost",size:"icon",className:"pn:size-[30px]","aria-label":n.isPlaying?"Pause":"Play",onClick:()=>{if(n.isPlaying){n.pause()}else{const e=n.currentTime>=n.duration?0:n.effectiveTime;n.play({startTime:e})}},children:n.isPlaying?e(t,{name:"pagesTimeline.pause",className:"pn:size-[25px]"}):e(t,{name:"pagesTimeline.play",className:"pn:size-[25px]"})})]}),m&&o&&i("div",{className:"pn:flex pn:items-center pn:justify-end pn:gap-1.5",children:[e("div",{className:"pn:text-xs pn:font-medium pn:tabular-nums pn:opacity-60",children:"Zoom timeline"}),i(s,{className:"pn:items-center",children:[e(a,{variant:"ghost",size:"icon-sm",className:"pn:size-[30px]",onClick:()=>{m&&o&&m(Math.max(o/1.5,.005))},title:"Zoom out timeline","aria-label":"Zoom out timeline",children:e("span",{className:"pn:font-bold",children:"−"})}),e(a,{variant:"ghost",size:"icon-sm",className:"pn:size-[30px]",onClick:()=>{m&&o&&m(Math.min(1.5*o,.2))},title:"Zoom in timeline","aria-label":"Zoom in timeline",children:e("span",{className:"pn:font-bold",children:"+"})})]})]})]})});