polotno 4.1.2 → 4.2.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/side-panel/select-video.d.ts +10 -0
- package/blueprint/toolbar/html-toolbar.js +2 -2
- package/canvas/drawing-layer.d.ts +3 -2
- package/canvas/drawing-layer.js +1 -1
- package/canvas/element.js +1 -1
- package/canvas/hotkeys.js +1 -1
- package/canvas/page-controls.js +1 -1
- package/canvas/page.js +1 -1
- package/canvas/quill-font-formats.js +1 -1
- package/canvas/render-tag-element.js +1 -1
- package/canvas/rich-editor.d.ts +3 -1
- package/canvas/rich-editor.js +16 -3
- package/canvas/rules.js +1 -1
- package/canvas/text-element/font-specs-loader.d.ts +3 -0
- package/canvas/text-element/font-specs-loader.js +1 -0
- package/canvas/workspace-canvas.js +1 -1
- package/config.d.ts +1 -1
- package/config.js +1 -1
- package/icons/registry.d.ts +2 -0
- package/icons/registry.js +1 -1
- package/model/figure-model.d.ts +5 -0
- package/model/gif-model.d.ts +5 -0
- package/model/group-model.d.ts +40 -0
- package/model/group-model.js +1 -1
- package/model/image-model.d.ts +5 -0
- package/model/line-model.d.ts +5 -0
- package/model/page-model.d.ts +56 -0
- package/model/page-model.js +1 -1
- package/model/shape-model.d.ts +5 -0
- package/model/shape-model.js +1 -1
- package/model/store.d.ts +521 -0
- package/model/store.js +1 -1
- package/model/svg-model.d.ts +5 -0
- package/model/table-model.d.ts +5 -0
- package/model/text-model.d.ts +5 -0
- package/model/video-model.d.ts +5 -0
- package/package.json +4 -3
- package/pages-timeline/current-time.js +1 -1
- package/pages-timeline/element-track.js +1 -1
- package/pages-timeline/elements.js +1 -1
- package/pages-timeline/page-preview.js +1 -1
- package/pages-timeline/play-button.js +1 -1
- package/polotno.bundle.js +206 -130
- package/side-panel/select-video.d.ts +10 -0
- package/side-panel/size-panel.js +1 -1
- package/themes/carbon.css +157 -0
- package/toolbar/download-button.js +1 -1
- package/toolbar/html-toolbar.js +4 -4
- package/toolbar/image-toolbar.js +1 -1
- package/toolbar/text-toolbar.js +1 -1
- package/toolbar/video-toolbar.js +1 -1
- package/ui.css +1 -1
- package/utils/fonts.js +1 -1
- package/utils/l10n.d.ts +8 -0
- package/utils/l10n.js +1 -1
- package/utils/rich-text-html.d.ts +12 -0
- package/utils/rich-text-html.js +1 -1
- package/utils/split-element.d.ts +2 -0
- package/utils/split-element.js +1 -0
- package/utils/text-format-state.js +1 -1
- package/utils/text-format.d.ts +2 -2
- package/utils/text-format.js +1 -1
- package/utils/text.js +1 -1
- package/utils/timeline.d.ts +3 -0
- package/utils/timeline.js +1 -1
- package/utils/to-html.js +1 -1
- package/utils/to-pptx.js +1 -1
- package/utils/to-svg.js +1 -1
- 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;
|
package/model/svg-model.d.ts
CHANGED
|
@@ -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
|
} & {
|
package/model/table-model.d.ts
CHANGED
|
@@ -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
|
} & {
|
package/model/text-model.d.ts
CHANGED
|
@@ -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
|
} & {
|
package/model/video-model.d.ts
CHANGED
|
@@ -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.
|
|
3
|
+
"version": "4.2.0",
|
|
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"
|
|
@@ -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.
|
|
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})=>{
|
|
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
|
|
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
|
|
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{
|
|
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:"+"})})]})]})]})});
|