@nylas/web-elements 0.0.0-test-20250321141510 → 0.0.0-test-20250327161320
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/dist/cdn/nylas-scheduler-editor/nylas-scheduler-editor.es.js +10 -11
- package/dist/cjs/calendar-agenda-fill-icon_36.cjs.entry.js +6 -9
- package/dist/cjs/calendar-agenda-fill-icon_36.cjs.entry.js.map +1 -1
- package/dist/cjs/google-logo-icon_6.cjs.entry.js +5 -5
- package/dist/cjs/google-logo-icon_6.cjs.entry.js.map +1 -1
- package/dist/cjs/nylas-scheduling.cjs.entry.js.map +1 -1
- package/dist/cjs/nylas-transcript.cjs.entry.js +4 -4
- package/dist/cjs/nylas-transcript.cjs.entry.js.map +1 -1
- package/dist/cjs/nylas-video-player.cjs.entry.js +2 -2
- package/dist/cjs/nylas-video-player.cjs.entry.js.map +1 -1
- package/dist/cjs/scheduler-store-461fd2ff.js.map +1 -1
- package/dist/collection/components/nylas-notebook/nylas-transcript/nylas-transcript.css +5 -0
- package/dist/collection/components/nylas-notebook/nylas-transcript/nylas-transcript.js +3 -3
- package/dist/collection/components/nylas-notebook/nylas-transcript/nylas-transcript.js.map +1 -1
- package/dist/collection/components/nylas-notebook/nylas-video-player/nylas-video-player.css +0 -3
- package/dist/collection/components/nylas-notebook/nylas-video-player/nylas-video-player.js +1 -1
- package/dist/collection/components/nylas-notebook/nylas-video-player/nylas-video-player.js.map +1 -1
- package/dist/collection/components/scheduler/nylas-scheduling/nylas-scheduling.js +1 -1
- package/dist/collection/components/scheduler/nylas-scheduling/nylas-scheduling.js.map +1 -1
- package/dist/collection/components/scheduler-editor/nylas-booking-form-config/nylas-booking-form-config.js +3 -5
- package/dist/collection/components/scheduler-editor/nylas-booking-form-config/nylas-booking-form-config.js.map +1 -1
- package/dist/collection/components/scheduler-editor/nylas-editor-tabs-group/nylas-editor-tabs-group.js +5 -5
- package/dist/collection/components/scheduler-editor/nylas-editor-tabs-group/nylas-editor-tabs-group.js.map +1 -1
- package/dist/collection/components/scheduler-editor/nylas-event-duration/test/nylas-event-duration-with-config-2.spec.js +58 -0
- package/dist/collection/components/scheduler-editor/nylas-event-duration/test/nylas-event-duration-with-config-2.spec.js.map +1 -0
- package/dist/collection/components/scheduler-editor/nylas-event-duration/test/nylas-event-duration-with-config.spec.js +0 -32
- package/dist/collection/components/scheduler-editor/nylas-event-duration/test/nylas-event-duration-with-config.spec.js.map +1 -1
- package/dist/collection/components/scheduler-editor/nylas-participants-custom-availability/nylas-participants-custom-availability.js +3 -4
- package/dist/collection/components/scheduler-editor/nylas-participants-custom-availability/nylas-participants-custom-availability.js.map +1 -1
- package/dist/collection/components/scheduler-editor/nylas-participants-custom-availability/test/nylas-participants-custom-availability.spec.js +12 -0
- package/dist/collection/components/scheduler-editor/nylas-participants-custom-availability/test/nylas-participants-custom-availability.spec.js.map +1 -1
- package/dist/collection/types/index.js.map +1 -1
- package/dist/components/nylas-booking-form-config2.js +3 -5
- package/dist/components/nylas-booking-form-config2.js.map +1 -1
- package/dist/components/nylas-editor-tabs-group2.js +5 -5
- package/dist/components/nylas-editor-tabs-group2.js.map +1 -1
- package/dist/components/nylas-participants-custom-availability2.js +3 -4
- package/dist/components/nylas-participants-custom-availability2.js.map +1 -1
- package/dist/components/nylas-scheduling.js.map +1 -1
- package/dist/components/nylas-transcript.js +4 -4
- package/dist/components/nylas-transcript.js.map +1 -1
- package/dist/components/nylas-video-player.js +2 -2
- package/dist/components/nylas-video-player.js.map +1 -1
- package/dist/components/scheduler-store.js.map +1 -1
- package/dist/esm/calendar-agenda-fill-icon_36.entry.js +6 -9
- package/dist/esm/calendar-agenda-fill-icon_36.entry.js.map +1 -1
- package/dist/esm/google-logo-icon_6.entry.js +5 -5
- package/dist/esm/google-logo-icon_6.entry.js.map +1 -1
- package/dist/esm/nylas-scheduling.entry.js.map +1 -1
- package/dist/esm/nylas-transcript.entry.js +4 -4
- package/dist/esm/nylas-transcript.entry.js.map +1 -1
- package/dist/esm/nylas-video-player.entry.js +2 -2
- package/dist/esm/nylas-video-player.entry.js.map +1 -1
- package/dist/esm/scheduler-store-755ced0b.js.map +1 -1
- package/dist/nylas-web-elements/nylas-web-elements.esm.js +1 -1
- package/dist/nylas-web-elements/p-4b48f29a.entry.js.map +1 -1
- package/dist/nylas-web-elements/{p-f12cd991.entry.js → p-7fcdad32.entry.js} +2 -2
- package/dist/nylas-web-elements/p-7fcdad32.entry.js.map +1 -0
- package/dist/nylas-web-elements/{p-b1c57792.entry.js → p-c3f848d7.entry.js} +2 -2
- package/dist/nylas-web-elements/{p-b1c57792.entry.js.map → p-c3f848d7.entry.js.map} +1 -1
- package/dist/nylas-web-elements/p-d1053aa8.entry.js +2 -0
- package/dist/nylas-web-elements/p-d1053aa8.entry.js.map +1 -0
- package/dist/nylas-web-elements/p-d36ad6ef.js.map +1 -1
- package/dist/nylas-web-elements/{p-11d7062d.entry.js → p-f4881c71.entry.js} +2 -2
- package/dist/nylas-web-elements/p-f4881c71.entry.js.map +1 -0
- package/package.json +3 -3
- package/dist/nylas-web-elements/p-11d7062d.entry.js.map +0 -1
- package/dist/nylas-web-elements/p-3d93df74.entry.js +0 -2
- package/dist/nylas-web-elements/p-3d93df74.entry.js.map +0 -1
- package/dist/nylas-web-elements/p-f12cd991.entry.js.map +0 -1
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
import{r as e,h as o,a as t}from"./p-6f5a3998.js";import{v as r}from"./p-890d7f01.js";import"./p-fc5bc07b.js";const i='.video-container{display:flex;flex-direction:column;align-items:center;justify-content:center;background-color:#000;position:relative;box-sizing:border-box;border-radius:8px;font-family:"Inter", serif;font-optical-sizing:auto}.video-container video{width:100%;border-radius:8px}.video-container .controls-overlay{color:white;background:linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.8));position:absolute;bottom:0;left:0;right:0;padding:30px 20px;padding-bottom:10px;opacity:1;transition:opacity 0.3s;border-bottom-right-radius:8px;border-bottom-left-radius:8px;display:none;}.video-container .controls-overlay .seek{width:100%}.video-container .controls-overlay input[type=range]{-webkit-appearance:none;appearance:none;background:transparent;cursor:pointer}.video-container .controls-overlay .info{padding-bottom:20px}.video-container .controls-overlay .info .title{font-size:20px}.video-container .controls-overlay .info .description{color:#bbbbbb;font-weight:400;font-size:14px}.video-container .controls-overlay .progress-bar{background-color:rgba(255, 255, 255, 0.5);height:2px;margin:10px 0;transition:width 0.1s}.video-container .controls-overlay .progress-bar .progress{background:white;height:2px}.video-container .controls-overlay .controls{display:flex;align-items:center;justify-content:space-between}.video-container .controls-overlay .controls button{background:none;border:none}.video-container .controls-overlay input[type=range]{-webkit-appearance:none;appearance:none;background:transparent;cursor:pointer;width:15rem}.video-container .controls-overlay input[type=range]:focus{outline:none}.video-container .controls-overlay input[type=range]::-webkit-slider-runnable-track{background-color:#053a5f;border-radius:0.5rem;height:0.5rem}.video-container .controls-overlay input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;margin-top:-12px;background-color:#5cd5eb;height:2rem;width:1rem}.video-container .controls-overlay input[type=range]:focus::-webkit-slider-thumb{border:1px solid #053a5f;outline:3px solid #053a5f;outline-offset:0.125rem}.video-container .controls-overlay input[type=range]::-moz-range-track{background-color:#053a5f;border-radius:0.5rem;height:0.5rem}.video-container .controls-overlay input[type=range]::-moz-range-thumb{border:none;border-radius:0;background-color:#5cd5eb;height:2rem;width:1rem}.video-container .controls-overlay input[type=range]:focus::-moz-range-thumb{border:1px solid #053a5f;outline:3px solid #053a5f;outline-offset:0.125rem}';const n=i;const a=class{constructor(o){e(this,o);this.handleTimeUpdate=()=>{const e=this.videoElement;r.set("videoTime",this.videoElement.currentTime);if(!this.isSeeking){this.seekElement.value=(e.currentTime/e.duration*100).toString()}};this.handlePlay=()=>{this.isPlaying=true;this.videoElement.play()};this.handlePause=()=>{this.isPlaying=false;this.videoElement.pause()};this.videoUrl=undefined;this.isSeeking=false;this.isPlaying=false}inputSeek(e){if(!this.isSeeking)this.isSeeking=true}handleSeek(e){this.isSeeking=false;if(!this.videoElement)return;const o=e.target;this.videoElement.currentTime=parseFloat(o.value)/100*this.videoElement.duration;this.videoElement.play()}get progressPercent(){if(!this.videoElement)return 0;const e=r.get("videoTime");return e/this.videoElement.duration*100}render(){return o("div",{key:"98a898e225274dac6fda72126de7eb3fbe3b73b0",class:"video-container"},o("video",{key:"6ff6bd22efd243b45f7ee92a8f01b4fbe392d4b1",ref:e=>this.videoElement=e,onPlay:this.handlePlay,onPause:this.handlePause,onTimeUpdate:this.handleTimeUpdate,controls:true},this.videoUrl&&o("source",{src:this.videoUrl,type:"video/mp4"})),o("div",{key:"2297c46d4b6d7803a884bbcf7c157573702880ed",class:"controls-overlay"},o("div",{key:"5207532096947074e5906edddab4e4c573d69795",class:"info"},o("div",{key:"f0f27ec9f18528ecae5cb705dcdd8579aee92f50",class:"title"},"Ad Video from Google"),o("div",{key:"b6c13515720c5706f6f30d588df1371ef1d435ae",class:"description"},"Found on the web...")),o("div",{key:"677f8ea6cbac199f4c5a3452e597dc0991c79d7a",class:"progress-bar"},o("input",{key:"e31aa4501345fb0eb2f6bbb1ebdad5317d8bface",type:"range",ref:e=>this.seekElement=e,min:"0",max:"100",class:"seek",value:this.progressPercent,onChange:e=>this.handleSeek(e),onClickCapture:e=>this.inputSeek(e)})),o("div",{key:"bdca2a6746d05ac8bc42feaf8a30029fb00c6cf4",class:"controls"},o("div",{key:"6c9d084306cb984770b28dce6d31cf268b62073e",class:"left"},o("button",{key:"6d128a31878bf394103bfcfb75c194d5733b5b6a",onClick:()=>this.handlePlay()}),o("button",{key:"cc3d3a8fb98b3c74bb8536f43726f71255045d24",onClick:()=>this.handlePause()})),o("div",{key:"e940328caf2215b148b97de6d0770d49f3621a5d",class:"right"},o("button",{key:"7feb3b396dc1463945ab6e44b6bfbcfe8c0e0e48",onClick:()=>this.handlePause()})))))}get el(){return t(this)}};a.style=n;export{a as nylas_video_player};
|
|
2
|
+
//# sourceMappingURL=p-d1053aa8.entry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["nylasVideoPlayerCss","NylasVideoPlayerStyle0","NylasVideoPlayer","this","handleTimeUpdate","videoElement","store","set","currentTime","isSeeking","seekElement","value","duration","toString","handlePlay","isPlaying","play","handlePause","pause","inputSeek","_e","handleSeek","e","target","parseFloat","progressPercent","get","render","h","key","class","ref","el","onPlay","onPause","onTimeUpdate","controls","videoUrl","src","type","min","max","onChange","onClickCapture","onClick"],"sources":["src/components/nylas-notebook/nylas-video-player/nylas-video-player.scss?tag=nylas-video-player&encapsulation=shadow","src/components/nylas-notebook/nylas-video-player/nylas-video-player.tsx"],"sourcesContent":[".video-container {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n background-color: #000;\n position: relative;\n box-sizing: border-box;\n border-radius: 8px;\n font-family: 'Inter', serif;\n font-optical-sizing: auto;\n\n video {\n width: 100%;\n border-radius: 8px;\n }\n\n .controls-overlay {\n color: white;\n background: linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.8));\n position: absolute;\n bottom: 0;\n left: 0;\n right: 0;\n padding: 30px 20px;\n padding-bottom: 10px;\n opacity: 1;\n transition: opacity 0.3s;\n border-bottom-right-radius: 8px;\n border-bottom-left-radius: 8px;\n display: none;\n\n .seek {\n width: 100%;\n }\n\n input[type='range'] {\n -webkit-appearance: none;\n appearance: none;\n background: transparent;\n cursor: pointer;\n }\n\n .info {\n padding-bottom: 20px;\n\n .title {\n font-size: 20px;\n }\n\n .description {\n color: #bbbbbb;\n font-weight: 400;\n font-size: 14px;\n }\n }\n\n .progress-bar {\n background-color: rgba(255, 255, 255, 0.5);\n height: 2px;\n margin: 10px 0;\n transition: width 0.1s;\n\n .progress {\n background: white;\n height: 2px;\n }\n }\n\n .controls {\n display: flex;\n align-items: center;\n justify-content: space-between;\n\n button {\n background: none;\n border: none;\n }\n }\n\n /********** Range Input Styles **********/\n /*Range Reset*/\n input[type='range'] {\n -webkit-appearance: none;\n appearance: none;\n background: transparent;\n cursor: pointer;\n width: 15rem;\n }\n\n /* Removes default focus */\n input[type='range']:focus {\n outline: none;\n }\n\n /***** Chrome, Safari, Opera and Edge Chromium styles *****/\n /* slider track */\n input[type='range']::-webkit-slider-runnable-track {\n background-color: #053a5f;\n border-radius: 0.5rem;\n height: 0.5rem;\n }\n\n /* slider thumb */\n input[type='range']::-webkit-slider-thumb {\n -webkit-appearance: none;\n /* Override default look */\n appearance: none;\n margin-top: -12px;\n /* Centers thumb on the track */\n\n /*custom styles*/\n background-color: #5cd5eb;\n height: 2rem;\n width: 1rem;\n }\n\n input[type='range']:focus::-webkit-slider-thumb {\n border: 1px solid #053a5f;\n outline: 3px solid #053a5f;\n outline-offset: 0.125rem;\n }\n\n /******** Firefox styles ********/\n /* slider track */\n input[type='range']::-moz-range-track {\n background-color: #053a5f;\n border-radius: 0.5rem;\n height: 0.5rem;\n }\n\n /* slider thumb */\n input[type='range']::-moz-range-thumb {\n border: none;\n /*Removes extra border that FF applies*/\n border-radius: 0;\n /*Removes default border-radius that FF applies*/\n\n /*custom styles*/\n background-color: #5cd5eb;\n height: 2rem;\n width: 1rem;\n }\n\n input[type='range']:focus::-moz-range-thumb {\n border: 1px solid #053a5f;\n outline: 3px solid #053a5f;\n outline-offset: 0.125rem;\n }\n }\n}\n","import { Component, h, Element, State, Prop } from '@stencil/core';\nimport { videoStore as store } from '../store/notebook-store';\n\n@Component({\n tag: 'nylas-video-player',\n shadow: true,\n styleUrl: './nylas-video-player.scss',\n})\nexport class NylasVideoPlayer {\n @Element() el!: HTMLElement;\n @Prop() videoUrl!: string;\n @State() isSeeking: boolean = false;\n @State() isPlaying: boolean = false;\n private videoElement!: HTMLVideoElement;\n private seekElement!: HTMLInputElement;\n\n handleTimeUpdate = () => {\n const videoElement = this.videoElement;\n store.set('videoTime', this.videoElement.currentTime);\n if (!this.isSeeking) {\n this.seekElement.value = ((videoElement.currentTime / videoElement.duration) * 100).toString();\n }\n };\n\n handlePlay = () => {\n this.isPlaying = true;\n this.videoElement.play();\n };\n\n handlePause = () => {\n this.isPlaying = false;\n this.videoElement.pause();\n };\n\n private inputSeek(_e: Event) {\n if (!this.isSeeking) this.isSeeking = true;\n }\n\n private handleSeek(e: Event) {\n this.isSeeking = false;\n if (!this.videoElement) return;\n const target = e.target as HTMLInputElement;\n this.videoElement.currentTime = (parseFloat(target.value) / 100) * this.videoElement.duration;\n this.videoElement.play();\n }\n\n get progressPercent() {\n if (!this.videoElement) return 0;\n const currentTime = store.get('videoTime');\n return (currentTime / this.videoElement.duration) * 100;\n }\n\n render() {\n return (\n <div class=\"video-container\">\n <video ref={el => (this.videoElement = el as HTMLVideoElement)} onPlay={this.handlePlay} onPause={this.handlePause} onTimeUpdate={this.handleTimeUpdate} controls>\n {this.videoUrl && <source src={this.videoUrl} type=\"video/mp4\" />}\n </video>\n <div class=\"controls-overlay\">\n <div class=\"info\">\n <div class=\"title\">Ad Video from Google</div>\n <div class=\"description\">Found on the web...</div>\n </div>\n <div class=\"progress-bar\">\n <input\n type=\"range\"\n ref={el => (this.seekElement = el as HTMLInputElement)}\n min=\"0\"\n max=\"100\"\n class=\"seek\"\n value={this.progressPercent}\n onChange={e => this.handleSeek(e)}\n onClickCapture={e => this.inputSeek(e)}\n />\n </div>\n <div class=\"controls\">\n <div class=\"left\">\n <button onClick={() => this.handlePlay()}>{/* <img src={playIcon} /> */}</button>\n <button onClick={() => this.handlePause()}>{/* <img src={volumeIcon} /> */}</button>\n </div>\n <div class=\"right\">\n <button onClick={() => this.handlePause()}>{/* <img src={fullScreenIcon} /> */}</button>\n </div>\n </div>\n </div>\n </div>\n );\n }\n}\n"],"mappings":"8GAAA,MAAMA,EAAsB,w+EAC5B,MAAAC,EAAeD,E,MCOFE,EAAgB,M,yBAQ3BC,KAAAC,iBAAmB,KACjB,MAAMC,EAAeF,KAAKE,aAC1BC,EAAMC,IAAI,YAAaJ,KAAKE,aAAaG,aACzC,IAAKL,KAAKM,UAAW,CACnBN,KAAKO,YAAYC,OAAUN,EAAaG,YAAcH,EAAaO,SAAY,KAAKC,U,GAIxFV,KAAAW,WAAa,KACXX,KAAKY,UAAY,KACjBZ,KAAKE,aAAaW,MAAM,EAG1Bb,KAAAc,YAAc,KACZd,KAAKY,UAAY,MACjBZ,KAAKE,aAAaa,OAAO,E,uCApBG,M,eACA,K,CAsBtB,SAAAC,CAAUC,GAChB,IAAKjB,KAAKM,UAAWN,KAAKM,UAAY,I,CAGhC,UAAAY,CAAWC,GACjBnB,KAAKM,UAAY,MACjB,IAAKN,KAAKE,aAAc,OACxB,MAAMkB,EAASD,EAAEC,OACjBpB,KAAKE,aAAaG,YAAegB,WAAWD,EAAOZ,OAAS,IAAOR,KAAKE,aAAaO,SACrFT,KAAKE,aAAaW,M,CAGpB,mBAAIS,GACF,IAAKtB,KAAKE,aAAc,OAAO,EAC/B,MAAMG,EAAcF,EAAMoB,IAAI,aAC9B,OAAQlB,EAAcL,KAAKE,aAAaO,SAAY,G,CAGtD,MAAAe,GACE,OACEC,EAAA,OAAAC,IAAA,2CAAKC,MAAM,mBACTF,EAAA,SAAAC,IAAA,2CAAOE,IAAKC,GAAO7B,KAAKE,aAAe2B,EAAyBC,OAAQ9B,KAAKW,WAAYoB,QAAS/B,KAAKc,YAAakB,aAAchC,KAAKC,iBAAkBgC,SAAQ,MAC9JjC,KAAKkC,UAAYT,EAAA,UAAQU,IAAKnC,KAAKkC,SAAUE,KAAK,eAErDX,EAAA,OAAAC,IAAA,2CAAKC,MAAM,oBACTF,EAAA,OAAAC,IAAA,2CAAKC,MAAM,QACTF,EAAA,OAAAC,IAAA,2CAAKC,MAAM,SAAO,wBAClBF,EAAA,OAAAC,IAAA,2CAAKC,MAAM,eAAa,wBAE1BF,EAAA,OAAAC,IAAA,2CAAKC,MAAM,gBACTF,EAAA,SAAAC,IAAA,2CACEU,KAAK,QACLR,IAAKC,GAAO7B,KAAKO,YAAcsB,EAC/BQ,IAAI,IACJC,IAAI,MACJX,MAAM,OACNnB,MAAOR,KAAKsB,gBACZiB,SAAUpB,GAAKnB,KAAKkB,WAAWC,GAC/BqB,eAAgBrB,GAAKnB,KAAKgB,UAAUG,MAGxCM,EAAA,OAAAC,IAAA,2CAAKC,MAAM,YACTF,EAAA,OAAAC,IAAA,2CAAKC,MAAM,QACTF,EAAA,UAAAC,IAAA,2CAAQe,QAAS,IAAMzC,KAAKW,eAC5Bc,EAAA,UAAAC,IAAA,2CAAQe,QAAS,IAAMzC,KAAKc,iBAE9BW,EAAA,OAAAC,IAAA,2CAAKC,MAAM,SACTF,EAAA,UAAAC,IAAA,2CAAQe,QAAS,IAAMzC,KAAKc,mB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NotificationType","ErrorCategory","ComponentErrorType","Errors","constructor","this","component","_title","category","Component","title","endtime_not_in_future","message","no_booking_info","no_timeslot_selected","no_timezone_selected","no_booking_id","no_salt","invalid_start_time","invalid_end_time","invalid_timezone","no_config_id","api","Api","invalid_session","general_error","internal_error","invalid_request_error","timeslot_not_available","provider_error","not_found_error","NylaSchedulerAPIConnector","schedulerAPIURL","schedulerStore","sessionId","configId","slug","clientId","errors","getHeaders","Authorization","makeAPIRequest","path","method","body","headers","schedulerURL","URL","version","pathname","response","fetch","decodeURIComponent","toString","Origin","window","location","origin","data","json","error","type","getErrorMessage","errorMessage","setConfigId","selectDate","date","set","selectTime","time","selectTimezone","timezone","selectLanguage","language","i18next","changeLanguage","toggleAdditionalData","value","refetchAvailability","setParticipantName","name","bookingInfo","state","primaryParticipant","setParticipantEmail","email","today","Date","startTime","getFullYear","getMonth","getTime","startTimeWithOffset","Math","floor","endTime","result","getAvailability","resetStoreStateAndFetchAvailability","firstAvailableDate","get","find","timeslot","start_time","_selectedDate","setReschedule","bookingID","eventInfo","getUISettings","finally","setCancel","setReject","resetCancel","goBack","resetConfirm","undefined","bookTimeslot","selectedTimeslot","selectedTimezone","selectedLanguage","t","order","participantToBookWith","emails","addFields","Object","entries","additionalFields","forEach","key","entry","primaryGuest","guests","additional_fields","configIdParam","url","length","JSON","stringify","additional_guests","guest","end_time","event_id","master_id","calendar_id","email_language","getTwoLetterLanguageCode","shift","includes","participants","startsWith","errorType","bookingId","split","getStartTimeWithMinBookingNotice","scheduler","min_booking_notice","getEndTimeForAvailableDaysInFuture","availableDaysInFuture","available_days_in_future","endTimeForAvailableDaysInFuture","addDaysToCurrentDate","endTimeWithOffset","min","params","URLSearchParams","now","nowTime","startOfMonth","endOfMonth","startTimeWithMinBooking","append","encodeURIComponent","rescheduleBookingId","queryString","availability","time_slots","map","availabilityTimeslotsFiltered","filter","availabilityTimeslotSorted","sort","a","b","cancelBooking","reason","action","cancellation_reason","booking_id","rescheduleBooking","apiErrors","componentErrors","i","time_zone","event","updateBooking","payload","status","salt","errorTitle","validateGroupEventTimeslot","configuration_id","CreateNylasSchedulerStore","defaultState","defaultNylasStoreState","selectedDate","navigator","Intl","DateTimeFormat","resolvedOptions","timeZone","showBookingForm","availabilityOrderEmails","selectableDates","eventDuration","cancelledEventInfo","isLoading","nylasBranding","debug","store","createStore","onChange","durationMinutes","reset"],"sources":["src/types/index.ts","src/connector/nylas-scheduler-connector/errors/index.ts","src/connector/shared/api/scheduler.ts","src/stores/scheduler-store.ts"],"sourcesContent":["export interface NylasResponse<Data = any> {\n request_id: string;\n data?: Data;\n error?: {\n message: string;\n type: string;\n };\n}\n\n// Avaliability\nexport interface OpenHours {\n days: number[];\n exDates: string[];\n timezone: string;\n start: string;\n end: string;\n}\n\nexport interface MeetingBuffer {\n before: number;\n after: number;\n}\n\n// Scheduling\nexport interface UpdateConfiguration extends Omit<Configuration, 'id'> {}\n\nexport interface ParticipantAvailability {\n calendar_ids: string[];\n open_hours?: OpenHours[];\n}\n\nexport type NylasSchedulerBookingParticipant = { name: string; email: string; nameReadOnly?: boolean; emailReadOnly?: boolean };\n\nexport type NylasSchedulerBookingData = {\n primaryParticipant: NylasSchedulerBookingParticipant;\n startTime?: Date;\n endTime?: Date;\n timezone?: string;\n language?: string;\n guests?: NylasSchedulerBookingParticipant[];\n additionalFields?: Record<\n string,\n {\n value: string;\n type?: string;\n readOnly?: boolean;\n }\n >;\n};\n\nexport type OpenHour = {\n days: number[]; // [1, 2, 3, 4, 5]\n start: string; // \"09:00\"\n end: string; // \"17:00\"\n timezone: string; // \"America/Los_Angeles\"\n};\n\nexport type Timeslot = {\n start_time: Date;\n end_time: Date;\n emails?: string[];\n capacity?: number;\n event_id?: string;\n master_id?: string;\n calendar_id?: string;\n};\n\nexport type ThemeConfig = Partial<{\n '--nylas-primary': string;\n '--nylas-info': string;\n '--nylas-success': string;\n '--nylas-warning': string;\n '--nylas-error': string;\n '--nylas-error-pressed': string;\n '--nylas-base-0': string;\n '--nylas-base-25': string;\n '--nylas-base-50': string;\n '--nylas-base-100': string;\n '--nylas-base-200': string;\n '--nylas-base-300': string;\n '--nylas-base-400': string;\n '--nylas-base-500': string;\n '--nylas-base-600': string;\n '--nylas-base-700': string;\n '--nylas-base-800': string;\n '--nylas-base-900': string;\n '--nylas-base-950': string;\n '--nylas-font-family': string;\n '--nylas-font-size': string;\n '--nylas-border-radius': string;\n '--nylas-border-radius-2x': string;\n '--nylas-border-radius-3x': string;\n}>;\n\nexport enum NotificationType {\n Error = 'error',\n Warning = 'warning',\n Info = 'info',\n Success = 'success',\n}\n\nexport type Notification = {\n id: string;\n type: NotificationType;\n title: string;\n code?: number;\n category: string;\n description?: string;\n ttl?: number | 'none';\n};\n\nexport type BookingType = 'booking' | 'organizer-confirmation' | 'custom-confirmation';\n\nexport type AvailabilityMethod = 'max-fairness' | 'max-availability' | 'collective';\n\nexport type ConferenceProvider = 'GoogleMeetConferenceProvider' | 'MicrosoftTeamsConferenceProvider' | 'ZoomConferenceProvider' | 'OnlineMeetingProviderMicrosoftTeams';\n\nexport type ReminderMethod = 'email' | 'webhook';\n\nexport interface Rules {\n availability_method: AvailabilityMethod;\n buffer: MeetingBuffer;\n default_open_hours: OpenHours[];\n round_robin_group_id: string;\n}\n\nexport interface ConferenceDetail {\n meeting_code?: string; // zoom, GTM, microsoft teams\n password?: string; // zoom, webex\n url?: string; // zoom, webex, GTM, meet, microsoft teams\n pin?: string; // webex, meet\n phone?: string[]; // GTM, meet, microsoft teams\n}\n\nexport interface Conference {\n provider?: ConferenceProvider;\n details?: ConferenceDetail;\n autocreate?: { [key: string]: any };\n}\n\nexport interface ParticipantBooking {\n calendar_id: string;\n}\n\nexport interface Participant {\n email: string;\n name?: string;\n is_organizer?: boolean;\n availability?: ParticipantAvailability;\n booking?: ParticipantBooking;\n}\n\nexport interface EventReminder {\n type: ReminderMethod;\n minutes_before_event: number;\n recipient?: string;\n email_subject?: string;\n}\n\nexport interface Availability {\n duration_minutes: number;\n interval_minutes?: number;\n round_to?: number;\n availability_rules?: Rules;\n}\n\nexport interface EventBooking {\n title: string;\n description?: string;\n location?: string;\n timezone?: string;\n booking_type: BookingType;\n conferencing?: Conference;\n hide_participants?: boolean;\n disable_emails?: boolean;\n reminders?: EventReminder[];\n}\n\nexport interface Appearance {\n color?: string;\n submit_button_label?: string;\n thank_you_message?: string;\n company_logo_url?: string;\n}\n\nexport interface Scheduler {\n available_days_in_future?: number;\n min_cancellation_notice: number;\n min_booking_notice?: number;\n rescheduling_url?: string;\n cancellation_url?: string;\n organizer_confirmation_url?: string;\n cancellation_policy?: string;\n hide_additional_guests?: boolean;\n hide_cancellation_options?: boolean;\n hide_rescheduling_options?: boolean;\n additional_fields?: Record<string, AdditionalFields>;\n email_template?: EmailTemplate;\n confirmation_redirect_url?: string;\n}\nexport interface AdditionalFields {\n type: string;\n required: boolean;\n order: number;\n options?: string[];\n label?: string;\n default?: string;\n}\n\nexport interface EmailTemplate {\n logo: string;\n booking_confirmed: BookingConfirmed;\n show_nylas_branding: boolean;\n}\n\nexport interface BookingConfirmed {\n title: string;\n body: string;\n}\n\nexport interface Configuration {\n id: string;\n version: string;\n type?: string;\n requires_session_auth?: boolean;\n participants: Participant[];\n availability: Availability;\n event_booking: EventBooking;\n scheduler: Partial<Scheduler>;\n slug: string;\n appearance: Appearance;\n name: string;\n}\n\nexport interface GroupBooking {\n booking_type: BookingType; // Only 'booking' is supported\n disable_emails?: boolean;\n reminders?: EventReminder[];\n conferencing?: Conference;\n calendar_id: string;\n default_capacity: number;\n}\n\nexport interface GroupConfiguration {\n id: string;\n name: string;\n slug: string;\n requires_session_auth?: boolean;\n type: 'group';\n group_booking: GroupBooking;\n scheduler: Scheduler;\n appearance: Appearance;\n}\n\nexport interface Creator {\n name: string;\n email: string;\n}\nexport interface AdditionalParticipant {\n name: string;\n email: string;\n calendars: {\n id: string;\n name: string;\n object?: 'calendar';\n is_primary?: boolean;\n is_owned_by_user?: boolean;\n read_only?: boolean;\n timezone?: string;\n }[];\n}\n\nexport interface GroupEvent {\n id?: string;\n title: string;\n busy: boolean;\n participants: NylasSchedulerBookingParticipant[];\n resources: {\n name: string;\n email: string;\n }[];\n description: string;\n when: {\n start_time: number;\n end_time: number;\n start_timezone?: string;\n end_timezone?: string;\n };\n location: string;\n rrule: string[];\n capacity: number;\n}\n\nexport type RecurrenceUpdateOption = 'this' | 'future' | 'all';\nexport type RecurrenceDeleteOption = 'this' | 'future' | 'all';\n\nexport type Snapshot = {\n busy: boolean;\n calendar_id: string;\n hide_participants: boolean;\n ical_uid: string;\n organizer: {\n name: string;\n email: string;\n };\n participants: {\n email: string;\n status: string;\n }[];\n resources: any[];\n read_only: boolean;\n recurrence: string[];\n reminders: {\n use_default: boolean;\n overrides: any[];\n };\n title: string;\n description?: string;\n location?: string;\n conferencing?: Conference;\n visibility: string;\n creator: {\n name: string;\n email: string;\n };\n html_link: string;\n grant_id: string;\n id: string;\n object: string;\n status: string;\n when: {\n start_timezone: string;\n end_timezone: string;\n object: string;\n start_time: number; // Unix timestamp\n end_time: number; // Unix timestamp\n };\n created_at: number; // Unix timestamp\n updated_at: number; // Unix timestamp\n};\n\nexport interface GroupEventAPIData {\n event: EventDetails;\n group_event_info?: GroupEventInfo;\n}\n\nexport type EventDetails = {\n busy: boolean;\n calendar_id: string;\n conferencing: {\n provider: ConferenceProvider;\n details: {\n meeting_code: string;\n url: string;\n pin: string;\n phone: string[];\n };\n };\n hide_participants: boolean;\n ical_uid: string;\n organizer: {\n name: string;\n email: string;\n };\n participants: Array<{\n email: string;\n status: 'yes' | 'no' | 'noreply';\n comment?: string;\n }>;\n resources: string[];\n read_only: boolean;\n reminders: {\n use_default: boolean;\n overrides: Array<{\n method?: string;\n minutes?: number;\n }>;\n };\n title: string;\n description?: string;\n location?: string;\n visibility: 'default' | 'public' | 'private';\n creator: {\n name: string;\n email: string;\n };\n html_link: string;\n master_event_id: string;\n color_id: string;\n grant_id: string;\n id: string;\n object: 'event';\n status: 'confirmed' | 'tentative' | 'cancelled';\n when: {\n start_timezone: string;\n end_timezone: string;\n object: 'timespan';\n start_time: number;\n end_time: number;\n };\n created_at: number;\n updated_at: number;\n original_start_time: number;\n};\n\nexport type GroupEventInfo = {\n event_id: string;\n calendar_id: string;\n master_id: string;\n config_id: string;\n capacity: number;\n type: 'updated_event' | 'single_event' | 'master_event';\n booked: boolean;\n finished: boolean;\n participants: Array<{\n email: string;\n is_organizer: boolean;\n name: string;\n timezone: string;\n }>;\n snapshot: any | null;\n snapshot_expires_at: number;\n rrule: string[] | null;\n exceptions: {\n event_id: string;\n capacity: number;\n participants: Array<{\n email: string;\n is_organizer: boolean;\n name: string;\n timezone: string;\n }>;\n }[];\n};\n\nexport type ImportGroupEventDetails = {\n event_id: string;\n calendar_id: string;\n capacity: number;\n participants: Participant[];\n organizer: {\n name: string;\n email: string;\n };\n};\n\nexport type ImportGroupEventResponse = {\n imported_events: string[];\n import_failed: {\n event_id: string;\n reason: string;\n }[];\n};\n\nexport enum ErrorCategory {\n Component = 'component',\n Api = 'api',\n Auth = 'auth',\n}\n\nexport interface ErrorDetails {\n title: string;\n message: string;\n category: ErrorCategory;\n}\n\nexport enum ComponentErrorType {\n endtime_not_in_future = 'endtime_not_in_future',\n no_booking_info = 'no_booking_info',\n no_timeslot_selected = 'no_timeslot_selected',\n no_timezone_selected = 'no_timezone_selected',\n no_booking_id = 'no_booking_id',\n no_salt = 'no_salt',\n invalid_start_time = 'invalid_start_time',\n invalid_end_time = 'invalid_end_time',\n invalid_timezone = 'invalid_timezone',\n no_config_id = 'no_config_id',\n}\n\nexport interface KeyPoint {\n time: number;\n text: string;\n active?: boolean;\n}","import { ComponentErrorType, ErrorCategory, ErrorDetails } from '@/types/index';\nimport { APIErrorType } from '@nylas/core';\nexport class Errors {\n component = (_title: string): Record<ComponentErrorType, (message?: string) => ErrorDetails> => {\n const category = ErrorCategory.Component;\n const title = `${_title} Error`;\n return {\n endtime_not_in_future: (message: string = '\"endtime\" can not be in the future') => {\n return {\n title,\n message,\n category,\n };\n },\n no_booking_info: (message: string = 'No booking info provided') => {\n return {\n title,\n message,\n category,\n };\n },\n no_timeslot_selected: (message: string = 'No timeslot selected') => {\n return {\n title,\n message,\n category,\n };\n },\n no_timezone_selected: (message: string = 'No timezone selected') => {\n return {\n title,\n message,\n category,\n };\n },\n no_booking_id: (message: string = 'No booking id provided') => {\n return {\n title,\n message,\n category,\n };\n },\n no_salt: (message: string = 'No salt provided') => {\n return {\n title,\n message,\n category,\n };\n },\n invalid_start_time: (message: string = 'Invalid start time') => {\n return {\n title,\n message,\n category,\n };\n },\n invalid_end_time: (message: string = 'Invalid end time') => {\n return {\n title,\n message,\n category,\n };\n },\n invalid_timezone: (message: string = 'Invalid timezone') => {\n return {\n title,\n message,\n category,\n };\n },\n no_config_id: (message: string = 'No configuration id provided') => {\n return {\n title,\n message,\n category,\n };\n },\n };\n };\n\n api = (_title: string): Record<APIErrorType, (message: string) => ErrorDetails> => {\n const category = ErrorCategory.Api;\n const title = `${_title} Error`;\n\n return {\n invalid_session: (message: string) => {\n return {\n title,\n message,\n category,\n };\n },\n general_error: (message: string) => {\n return {\n title,\n message,\n category,\n };\n },\n internal_error: (message: string) => {\n return {\n title,\n message,\n category,\n };\n },\n invalid_request_error: (message: string) => {\n return {\n title,\n message,\n category,\n };\n },\n timeslot_not_available: (message: string) => {\n return {\n title,\n message,\n category,\n };\n },\n provider_error: (message: string) => {\n return {\n title,\n message,\n category,\n };\n },\n not_found_error: (message: string) => {\n return {\n title,\n message,\n category,\n };\n },\n };\n };\n}\n","import { AvailabilityResponse, NylasSchedulerBookingData, NylasSchedulerBookingDataWithFlatFields, NylasEvent, UISettingsResponse } from '@/common/types';\nimport { NylasSchedulerStoreType } from '../../../components';\nimport type { NylasErrorResponse, NylasResponse, NylasSchedulerResponse, Timeslot } from '@nylas/core';\nimport { Errors } from '@/connector/nylas-scheduler-connector/errors';\nimport { addDaysToCurrentDate } from '@/utils/utils';\nimport i18next from '@/utils/i18n';\nimport { APIErrorType } from '@nylas/core';\n\ntype NylasSchedulerAPIConnectorOptions = {\n schedulerAPIURL: string;\n schedulerStore: NylasSchedulerStoreType;\n sessionId?: string;\n configId?: string;\n slug?: string;\n clientId?: string;\n};\n\n/**\n * NylaSchedulerConnector\n * This class is used to make API requests to the scheduler.\n */\nexport class NylaSchedulerAPIConnector {\n private schedulerStore: NylasSchedulerStoreType;\n private schedulerAPIURL: string;\n private sessionId: string | undefined;\n private configId: string | undefined;\n private slug: string | undefined;\n private clientId: string | undefined;\n private errors = new Errors();\n\n constructor({ schedulerAPIURL, schedulerStore, sessionId, configId, slug, clientId }: NylasSchedulerAPIConnectorOptions) {\n this.schedulerStore = schedulerStore;\n this.schedulerAPIURL = schedulerAPIURL;\n this.sessionId = sessionId;\n this.configId = configId;\n this.slug = slug;\n this.clientId = clientId;\n }\n\n private getHeaders() {\n return this.sessionId\n ? {\n Authorization: `Bearer ${this.sessionId}`,\n }\n : {};\n }\n\n /**\n * Makes an API request to the scheduler.\n * @param path The path to the API endpoint.\n * @param method The HTTP method.\n * @param body The request body (if any).\n * @returns {Promise<T>}\n */\n public async makeAPIRequest<T>(path: string, method: string, body: string | undefined, headers = {}): Promise<NylasResponse<T>> {\n try {\n const schedulerURL = new URL(this.schedulerAPIURL);\n const version = process.env.PACKAGE_VERSION || 'latest';\n schedulerURL.pathname = path;\n const response = await fetch(decodeURIComponent(schedulerURL.toString()), {\n method,\n headers: {\n 'Content-Type': 'application/json',\n 'Origin': window.location.origin,\n 'X-Source': 'nylas-scheduling',\n 'X-Nylas-Web-Elements-Version': version,\n ...headers,\n },\n body,\n });\n // The server returns a json object for errors: eg.\n // {\n // \"request_id\": \"<request_id>\",\n // \"error\": {\n // \"type\": \"not_found_error\",\n // \"message\": \"Session not found\"\n // }\n // }\n const data = await response.json();\n return data as NylasResponse<T>;\n } catch (error: any) {\n // NOTE: current server implementation doesn't return a JSON object for errors on some endpoints\n // handle this case by returning the error response as a string to be handled downstream\n return {\n error: {\n message: error.message,\n title: 'API request failed',\n type: 'api',\n },\n } as NylasErrorResponse;\n }\n }\n\n private getErrorMessage(error: NylasErrorResponse['error']) {\n let errorMessage = error?.message || error?.title || 'Something went wrong';\n if (error?.type === 'provider_error') {\n errorMessage = error?.provider_error?.error?.message || error?.provider_error?.error?.title || 'Something went wrong';\n }\n return errorMessage;\n }\n\n public setConfigId(configId: string) {\n this.configId = configId;\n }\n\n /**\n * Selects a date in the scheduler.\n */\n public selectDate(date: Date) {\n this.schedulerStore.set('selectedDate', date);\n this.schedulerStore.set('selectedTimeslot', null);\n }\n\n /**\n * Selects a time in the scheduler.\n */\n public selectTime(time: Timeslot) {\n this.schedulerStore.set('selectedTimeslot', time);\n }\n\n /**\n * Sets the timezone in the scheduler.\n */\n public selectTimezone(timezone: string) {\n this.schedulerStore.set('selectedTimezone', timezone);\n }\n\n /**\n * Sets the language in the scheduler.\n */\n public selectLanguage(language: string) {\n this.schedulerStore.set('selectedLanguage', language);\n i18next.changeLanguage(language);\n }\n\n /**\n * Toggles showBookingForm\n * @param value boolean\n */\n public async toggleAdditionalData(value: boolean) {\n if (!value) {\n // Refetch availability\n await this.refetchAvailability();\n }\n this.schedulerStore.set('showBookingForm', value);\n }\n\n /**\n * Set/update the name of the participant booking the event.\n */\n public setParticipantName(name: string) {\n const { bookingInfo } = this.schedulerStore.state;\n this.schedulerStore.set('bookingInfo', {\n ...bookingInfo,\n primaryParticipant: {\n ...(bookingInfo?.primaryParticipant as NylasSchedulerBookingData['primaryParticipant']),\n name,\n },\n });\n }\n\n /**\n * Set/update the email of the participant booking the event.\n */\n public setParticipantEmail(email: string) {\n const { bookingInfo } = this.schedulerStore.state;\n this.schedulerStore.set('bookingInfo', {\n ...bookingInfo,\n primaryParticipant: {\n ...(bookingInfo?.primaryParticipant as NylasSchedulerBookingData['primaryParticipant']),\n email,\n },\n });\n }\n\n private async refetchAvailability() {\n const today = new Date();\n // Refetch availability\n const startTime = new Date(today.getFullYear(), today.getMonth(), 1).getTime() / 1000;\n const startTimeWithOffset = startTime < today.getTime() / 1000 ? Math.floor(today.getTime() / 1000) : startTime;\n const endTime = new Date(today.getFullYear(), today.getMonth() + 1, 1).getTime() / 1000;\n const result = await this.getAvailability(startTimeWithOffset, endTime);\n return result;\n }\n\n private async resetStoreStateAndFetchAvailability() {\n const today = new Date();\n // Refetch availability\n const result = await this.refetchAvailability();\n // Set selected date to first available date\n const firstAvailableDate = this.schedulerStore.get('availability').find((timeslot: any) => new Date(timeslot.start_time) > new Date());\n let _selectedDate = today;\n if (firstAvailableDate) {\n _selectedDate = firstAvailableDate.start_time;\n }\n this.schedulerStore.set('selectedDate', _selectedDate);\n // Reset store state\n this.schedulerStore.set('eventInfo', null);\n this.schedulerStore.set('showBookingForm', false);\n this.schedulerStore.set('selectedTimeslot', null);\n\n return result;\n }\n\n /**\n * Set reschedule booking id\n */\n public async setReschedule(bookingID: string) {\n this.schedulerStore.set('isLoading', true);\n const eventInfo = this.schedulerStore.state.eventInfo;\n if (eventInfo) {\n this.schedulerStore.set('reschedulingEventInfo', eventInfo);\n }\n this.schedulerStore.set('rescheduleBookingId', bookingID);\n await this.getUISettings();\n // Set reschedule booking id\n const result = await this.resetStoreStateAndFetchAvailability().finally(() => {\n this.schedulerStore.set('isLoading', false);\n });\n\n return result;\n }\n\n /**\n * Set cancel booking id\n */\n public async setCancel(bookingID: string) {\n this.schedulerStore.set('cancelBookingId', bookingID);\n }\n\n /**\n * Set reject booking id\n */\n public async setReject(bookingID: string) {\n this.schedulerStore.set('rejectBookingId', bookingID);\n }\n\n public async resetCancel() {\n const result = await this.resetStoreStateAndFetchAvailability();\n this.schedulerStore.set('cancelBookingId', '');\n this.schedulerStore.set('rejectBookingId', '');\n this.schedulerStore.set('cancelledEventInfo', null);\n return result;\n }\n\n public async goBack() {\n this.schedulerStore.set('cancelBookingId', '');\n return;\n }\n\n public async resetConfirm() {\n const result = await this.resetStoreStateAndFetchAvailability();\n this.schedulerStore.set('organizerConfirmationBookingId', '');\n this.schedulerStore.set('confirmedEventInfo', undefined);\n return result;\n }\n\n /**\n * Book the selected timeslot.\n * @param data The booking info.\n * @returns {Promise<NylasResponse<NylasEvent>>}\n */\n public async bookTimeslot(data?: NylasSchedulerBookingDataWithFlatFields & { timeslot?: Timeslot }): Promise<NylasSchedulerResponse<NylasEvent>> {\n this.schedulerStore.set('isLoading', true);\n const { selectedTimeslot, selectedTimezone, bookingInfo, selectedLanguage } = this.schedulerStore.state;\n\n if (!data && !bookingInfo) {\n return { error: this.errors.component(i18next.t('createBookingErrorTitle')).no_booking_info() };\n }\n\n const timeslot = data?.timeslot || selectedTimeslot;\n if (!timeslot) {\n return { error: this.errors.component(i18next.t('createBookingErrorTitle')).no_timeslot_selected() };\n }\n\n const timezone = data && data?.timezone ? data?.timezone : selectedTimezone;\n const language = selectedLanguage || 'en-US';\n\n if (!timezone) {\n return { error: this.errors.component(i18next.t('createBookingErrorTitle')).no_timezone_selected() };\n }\n\n const order = [...this.schedulerStore.get('availabilityOrderEmails')];\n\n let participantToBookWith = '';\n const emails = timeslot?.emails || [];\n\n const addFields = {};\n Object.entries(bookingInfo?.additionalFields || {}).forEach(([key, entry]) => {\n addFields[key] = (entry as { value: string; type?: string }).value;\n });\n\n const primaryGuest = data ? data?.primaryParticipant : bookingInfo?.primaryParticipant;\n const guests = data ? data?.guests || [] : bookingInfo?.guests || [];\n const additional_fields = data ? data?.additionalFields : addFields;\n\n const headers = this.getHeaders();\n const configIdParam =\n !this.sessionId && this.configId\n ? `?configuration_id=${this.configId}`\n : !this.sessionId && this.slug && this.clientId\n ? `?slug=${this.slug}&client_id=${this.clientId}`\n : '';\n const url = `/v3/scheduling/bookings${configIdParam}`;\n\n // If the order array is empty, make a single request without retries\n if (order.length === 0) {\n const response = await this.makeAPIRequest<NylasEvent>(\n decodeURIComponent(url),\n 'POST',\n JSON.stringify({\n additional_fields,\n additional_guests: guests,\n guest: { ...primaryGuest },\n start_time: timeslot.start_time.getTime() / 1000,\n end_time: timeslot.end_time.getTime() / 1000,\n timezone,\n event_id: timeslot?.event_id || undefined,\n master_id: timeslot?.master_id || undefined,\n calendar_id: timeslot?.calendar_id || undefined,\n email_language: this.getTwoLetterLanguageCode(language),\n }),\n headers,\n );\n\n this.schedulerStore.set('isLoading', false);\n if ('data' in response) {\n this.schedulerStore.set('eventInfo', response.data);\n return response;\n }\n return { error: response.error };\n }\n\n while (order.length > 0) {\n participantToBookWith = order.shift()!;\n\n if (!emails.includes(participantToBookWith)) {\n continue; // Skip if the email is not part of the timeslot\n }\n\n const response = await this.makeAPIRequest<NylasEvent>(\n decodeURIComponent(url),\n 'POST',\n JSON.stringify({\n participants: participantToBookWith ? [{ email: participantToBookWith }] : undefined,\n additional_fields,\n additional_guests: guests,\n guest: { ...primaryGuest },\n start_time: timeslot.start_time.getTime() / 1000,\n end_time: timeslot.end_time.getTime() / 1000,\n timezone: timezone,\n email_language: this.getTwoLetterLanguageCode(language),\n }),\n headers,\n );\n\n if ('data' in response) {\n // Successful booking\n this.schedulerStore.set('isLoading', false);\n this.schedulerStore.set('eventInfo', response?.data);\n return response;\n } else if (response.error?.message?.startsWith('The selected timeslot is unavailable')) {\n // Retry with the next email in the order\n continue;\n } else {\n // Return other errors\n this.schedulerStore.set('isLoading', false);\n const errorType = response.error?.type;\n let error = response.error;\n if (errorType && errorType in this.errors.api(i18next.t('createBookingErrorTitle'))) {\n const errorMessage = this.getErrorMessage(error);\n error = this.errors.api(i18next.t('createBookingErrorTitle'))[errorType as APIErrorType](errorMessage);\n }\n return { error };\n }\n }\n\n // If no emails in order succeed\n this.schedulerStore.set('isLoading', false);\n return {\n error: this.errors.api(i18next.t('createBookingErrorTitle')).timeslot_not_available('The selected timeslot is unavailable'),\n };\n }\n\n /**\n * Get UI settings for the scheduler.\n */\n public async getUISettings(): Promise<NylasSchedulerResponse<UISettingsResponse>> {\n this.schedulerStore.set('isLoading', true);\n const bookingId = this.schedulerStore.get('rescheduleBookingId');\n const headers = this.getHeaders();\n let configIdParam =\n !this.sessionId && this.configId\n ? `?configuration_id=${this.configId}`\n : !this.sessionId && this.slug && this.clientId\n ? `?slug=${this.slug}&client_id=${this.clientId}`\n : '';\n if (bookingId && !!configIdParam) {\n configIdParam += `&booking_id=${bookingId}`;\n } else if (bookingId) {\n configIdParam += `?booking_id=${bookingId}`;\n }\n\n const url = `/v3/scheduling/ui-settings${configIdParam}`;\n\n const response = await this.makeAPIRequest<UISettingsResponse>(url, 'GET', undefined, headers);\n if ('error' in response) {\n this.schedulerStore.set('isLoading', false);\n const errorType = response.error?.type;\n let error = response.error;\n if (errorType && errorType in this.errors.api(i18next.t('getUISettingErrorTitle'))) {\n error = this.errors.api(i18next.t('getUISettingErrorTitle'))[errorType as APIErrorType](error?.message || error?.title || 'Something went wrong');\n }\n return { error };\n }\n if ('data' in response) {\n this.schedulerStore.set('configSettings', response.data);\n }\n this.schedulerStore.set('isLoading', false);\n return response;\n }\n\n private getTwoLetterLanguageCode(language: string) {\n return language.split('-')[0];\n }\n\n private getStartTimeWithMinBookingNotice(startTime: number) {\n const scheduler = this.schedulerStore.get('configSettings')?.scheduler;\n const min_booking_notice = scheduler?.min_booking_notice;\n if (!min_booking_notice) {\n return startTime;\n }\n const today = new Date().getTime();\n\n if (startTime < (today + min_booking_notice * 60 * 1000) / 1000) {\n return Math.floor((today + min_booking_notice * 60 * 1000) / 1000);\n } else {\n return startTime;\n }\n }\n\n private getEndTimeForAvailableDaysInFuture(endTime: number) {\n const today = new Date();\n const availableDaysInFuture = this.schedulerStore.get('configSettings')?.scheduler?.available_days_in_future;\n const endTimeForAvailableDaysInFuture = Math.floor(addDaysToCurrentDate(today, availableDaysInFuture).getTime() / 1000);\n const endTimeWithOffset = Math.min(endTimeForAvailableDaysInFuture, endTime);\n return endTimeWithOffset;\n }\n\n /**\n * Gets the availability for a page.\n * @param startTime The start time.\n * @param endTime The end time.\n * @returns {Promise<AvailabilityResponse>}\n */\n public async getAvailability(startTime: number = 0, endTime: number = 0): Promise<NylasSchedulerResponse<AvailabilityResponse>> {\n this.schedulerStore.set('isLoading', true);\n const params = new URLSearchParams();\n const now = new Date();\n const nowTime = now.getTime();\n\n if (endTime && endTime < nowTime / 1000) {\n this.schedulerStore.set('isLoading', false);\n const error = this.errors.component(i18next.t('getAvailabilityErrorTitle')).endtime_not_in_future();\n return { error };\n }\n\n // Calculate the start of the current month if startTime is not provided\n if (!startTime) {\n const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);\n startTime = Math.floor(startOfMonth.getTime() / 1000); // Convert to UNIX timestamp in seconds\n }\n\n // Calculate the end of the current month if endTime is not provided\n if (!endTime) {\n const endOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0); // Setting day to 0 gets the last day of the previous month, so in this case, the last day of the current month\n endTime = Math.floor(endOfMonth.getTime() / 1000); // Convert to UNIX timestamp in seconds\n }\n\n endTime = this.getEndTimeForAvailableDaysInFuture(endTime);\n const startTimeWithMinBooking = this.getStartTimeWithMinBookingNotice(startTime);\n startTime = startTimeWithMinBooking;\n endTime = startTimeWithMinBooking > endTime ? startTimeWithMinBooking + 1 : endTime;\n\n params.append('start_time', encodeURIComponent(startTime.toString()));\n params.append('end_time', encodeURIComponent(endTime.toString()));\n if (this.configId && !this.sessionId) {\n params.append('configuration_id', encodeURIComponent(this.configId));\n } else if (this.slug && this.clientId && !this.sessionId) {\n params.append('slug', encodeURIComponent(this.slug));\n params.append('client_id', encodeURIComponent(this.clientId));\n }\n\n const rescheduleBookingId = this.schedulerStore.get('rescheduleBookingId');\n if (rescheduleBookingId) {\n params.append('booking_id', encodeURIComponent(rescheduleBookingId));\n }\n const queryString = params.toString();\n const url = `/v3/scheduling/availability${queryString ? `?${queryString}` : ''}`;\n const headers = this.getHeaders();\n const response = await this.makeAPIRequest<AvailabilityResponse>(decodeURIComponent(url), 'GET', undefined, headers);\n\n if ('error' in response) {\n this.schedulerStore.set('availability', []);\n this.schedulerStore.set('isLoading', false);\n const errorType = response.error?.type;\n let error = response.error;\n if (errorType && errorType in this.errors.api(i18next.t('getAvailabilityErrorTitle'))) {\n const errorMessage = this.getErrorMessage(error);\n error = this.errors.api(i18next.t('getAvailabilityErrorTitle'))[errorType as APIErrorType](errorMessage);\n }\n return { error };\n }\n\n if ('data' in response) {\n const availability =\n response.data?.time_slots?.map(timeslot => {\n return {\n ...timeslot,\n start_time: new Date(timeslot.start_time * 1000),\n end_time: new Date(timeslot.end_time * 1000),\n };\n }) || [];\n\n // Filter out timeslots that are in the past\n const availabilityTimeslotsFiltered = availability.filter(timeslot => timeslot.start_time.getTime() > nowTime);\n const availabilityTimeslotSorted = availabilityTimeslotsFiltered.sort((a, b) => a.start_time.getTime() - b.start_time.getTime());\n this.schedulerStore.set('availability', availabilityTimeslotSorted);\n const order = response.data?.order || [];\n this.schedulerStore.set('availabilityOrderEmails', order);\n }\n\n this.schedulerStore.set('isLoading', false);\n return response;\n }\n\n /**\n * Cancels a booking.\n * @param bookingId The booking ID.\n */\n public async cancelBooking(bookingId: string, reason: string): Promise<NylasSchedulerResponse<Partial<NylasEvent>>> {\n this.schedulerStore.set('isLoading', true);\n if (!bookingId) {\n return { error: this.errors.component(i18next.t('cancelBookingErrorTitle')).no_booking_id() };\n }\n const configIdParam =\n !this.sessionId && this.configId\n ? `?configuration_id=${this.configId}`\n : !this.sessionId && this.slug && this.clientId\n ? `?slug=${this.slug}&client_id=${this.clientId}`\n : '';\n const url = `/v3/scheduling/bookings/${bookingId}${configIdParam}`;\n const headers = this.getHeaders();\n const response = await this.makeAPIRequest<Partial<NylasEvent>>(\n decodeURIComponent(url),\n 'DELETE',\n JSON.stringify({\n action: 'cancel',\n cancellation_reason: reason,\n }),\n headers,\n );\n\n if ('error' in response) {\n this.schedulerStore.set('isLoading', false);\n const errorType = response.error?.type;\n let error = response.error;\n if (errorType && errorType in this.errors.api(i18next.t('cancelBookingErrorTitle'))) {\n const errorMessage = this.getErrorMessage(error);\n error = this.errors.api(i18next.t('cancelBookingErrorTitle'))[errorType as APIErrorType](errorMessage);\n }\n return { error };\n }\n\n this.schedulerStore.set('cancelledEventInfo', {\n booking_id: bookingId,\n });\n this.schedulerStore.set('rescheduleBookingId', '');\n this.schedulerStore.set('isLoading', false);\n return response;\n }\n\n /**\n * Reschedules a booking.\n * @param bookingId The booking ID.\n * @param data The booking info.\n * @returns {Promise<NylasResponse<NylasEvent>>}\n */\n public async rescheduleBooking(bookingId: string, data: NylasSchedulerBookingDataWithFlatFields): Promise<NylasSchedulerResponse<NylasEvent>> {\n this.schedulerStore.set('isLoading', true);\n if (!bookingId) {\n return { error: this.errors.component(i18next.t('rescheduleBookingErrorTitle')).no_booking_id() };\n }\n const apiErrors = this.errors.api(i18next.t('rescheduleBookingErrorTitle'));\n const componentErrors = this.errors.component(i18next.t('rescheduleBookingErrorTitle'));\n const { bookingInfo, selectedTimeslot, selectedTimezone, selectedLanguage } = this.schedulerStore.state;\n // Validate data\n const { startTime, endTime, timezone } = data;\n const start_time = startTime || selectedTimeslot?.start_time;\n\n if (!start_time) {\n return { error: componentErrors.invalid_start_time('Please pass \"startTime\" in data or set \"selectedTimeslot\" in the defaultSchedulerState.') };\n }\n const end_time = endTime || selectedTimeslot?.end_time;\n if (!end_time) {\n return { error: componentErrors.invalid_end_time('Please pass \"endTime\" in data or set \"selectedTimeslot\" in the defaultSchedulerState.') };\n }\n\n const order = this.schedulerStore.get('availabilityOrderEmails');\n let participantToBookWith = '';\n if (order.length > 0) {\n // Get the emails in the timeslot\n const emails = selectedTimeslot?.emails || [];\n for (let i = 0; i < order.length; i++) {\n if (emails.includes(order[i])) {\n participantToBookWith = order[i];\n break;\n }\n }\n }\n\n const time_zone = timezone || selectedTimezone;\n if (!time_zone) {\n return { error: componentErrors.invalid_timezone('Please pass \"timezone\" in data or set \"selectedTimezone\" in the defaultSchedulerState.') };\n }\n const addFields = {};\n Object.entries(bookingInfo?.additionalFields || {}).forEach(([key, entry]) => {\n addFields[key] = (entry as { value: string; type?: string }).value;\n });\n const primaryGuest = data ? data?.primaryParticipant : bookingInfo?.primaryParticipant;\n const guests = data ? data?.guests || [] : bookingInfo?.guests || [];\n const additional_fields = data ? data?.additionalFields : addFields;\n\n const configIdParam =\n !this.sessionId && this.configId\n ? `?configuration_id=${this.configId}`\n : !this.sessionId && this.slug && this.clientId\n ? `?slug=${this.slug}&client_id=${this.clientId}`\n : '';\n const url = `/v3/scheduling/bookings/${bookingId}${configIdParam}`;\n const headers = this.getHeaders();\n const response = await this.makeAPIRequest<NylasEvent>(\n decodeURIComponent(url),\n 'PATCH',\n JSON.stringify({\n start_time: start_time.getTime() / 1000,\n end_time: end_time.getTime() / 1000,\n timezone: time_zone,\n additional_fields,\n guest: { ...primaryGuest },\n additional_guests: guests,\n participants: participantToBookWith ? [{ email: participantToBookWith }] : undefined,\n email_language: this.getTwoLetterLanguageCode(selectedLanguage),\n }),\n headers,\n );\n\n if ('error' in response) {\n this.schedulerStore.set('isLoading', false);\n const errorType = response.error?.type;\n let error = response.error;\n if (errorType && errorType in apiErrors) {\n const errorMessage = this.getErrorMessage(error);\n error = apiErrors[errorType as APIErrorType](errorMessage);\n }\n return { error };\n }\n\n const eventInfo = this.schedulerStore.get('reschedulingEventInfo');\n if ('data' in response) {\n this.schedulerStore.set('eventInfo', response?.data);\n } else if (eventInfo) {\n this.schedulerStore.set('eventInfo', eventInfo);\n } else {\n // We should technically never reach this point\n const event = {\n booking_id: bookingId,\n } as NylasEvent;\n this.schedulerStore.set('eventInfo', event);\n }\n\n this.schedulerStore.set('isLoading', false);\n return response;\n }\n\n /**\n * Updates the booking.\n * @param bookingId The booking ID.\n */\n public async updateBooking(payload: { bookingId: string; status: 'confirmed' | 'cancelled'; reason?: string }): Promise<NylasSchedulerResponse<NylasEvent>> {\n this.schedulerStore.set('isLoading', true);\n const { bookingId, status, reason } = payload;\n const salt = this.schedulerStore.get('organizerConfirmationSalt');\n const errorTitle = status === 'confirmed' ? i18next.t('confirmBookingErrorTitle') : i18next.t('rejectBookingErrorTitle');\n\n if (!bookingId) {\n return { error: this.errors.component(errorTitle).no_booking_id() };\n }\n if (!salt) {\n return { error: this.errors.component(errorTitle).no_salt() };\n }\n\n const configIdParam =\n !this.sessionId && this.configId\n ? `?configuration_id=${this.configId}`\n : !this.sessionId && this.slug && this.clientId\n ? `?slug=${this.slug}&client_id=${this.clientId}`\n : '';\n const url = `/v3/scheduling/bookings/${bookingId}${configIdParam}`;\n const headers = this.getHeaders();\n const response = await this.makeAPIRequest<NylasEvent>(\n decodeURIComponent(url),\n 'PUT',\n JSON.stringify({\n status: status,\n cancellation_reason: reason,\n salt,\n }),\n headers,\n );\n\n if ('error' in response) {\n this.schedulerStore.set('isLoading', false);\n const errorType = response.error?.type;\n let error = response.error;\n if (errorType && errorType in this.errors.api(errorTitle)) {\n const errorMessage = this.getErrorMessage(error);\n error = this.errors.api(errorTitle)[errorType as APIErrorType](errorMessage);\n }\n return { error };\n }\n\n if ('data' in response && status === 'confirmed') {\n this.schedulerStore.set('confirmedEventInfo', response?.data);\n } else if ('request_id' in response && status === 'cancelled') {\n this.schedulerStore.set('cancelledEventInfo', {\n booking_id: bookingId,\n });\n }\n\n this.schedulerStore.set('organizerConfirmationBookingId', '');\n this.schedulerStore.set('isLoading', false);\n return response;\n }\n\n /**\n * Validate timeslot for group event booking\n */\n public async validateGroupEventTimeslot(timeslot: Timeslot) {\n this.schedulerStore.set('isLoading', true);\n const configId = this.schedulerStore.get('configSettings')?.configuration_id;\n if (!configId) {\n return { error: this.errors.component(i18next.t('validateTimeslotErrorTitle')).no_config_id() };\n }\n\n const headers = this.getHeaders();\n const url = `/v3/scheduling/configurations/${configId}/group-events/validate-timeslot`;\n const response = await this.makeAPIRequest<NylasEvent>(\n decodeURIComponent(url),\n 'POST',\n JSON.stringify({\n ...timeslot,\n start_time: timeslot.start_time.getTime() / 1000,\n end_time: timeslot.end_time.getTime() / 1000,\n }),\n headers,\n );\n\n if ('error' in response) {\n this.schedulerStore.set('isLoading', false);\n const errorType = response.error?.type;\n let error = response.error;\n if (errorType && errorType in this.errors.api(i18next.t('validateTimeslotErrorTitle'))) {\n const errorMessage = this.getErrorMessage(error);\n error = this.errors.api(i18next.t('validateTimeslotErrorTitle'))[errorType as APIErrorType](errorMessage);\n }\n this.refetchAvailability();\n return { error };\n }\n\n this.schedulerStore.set('selectedTimeslot', timeslot);\n this.schedulerStore.set('showBookingForm', true);\n this.schedulerStore.set('isLoading', false);\n return response;\n }\n}\n","import { DataState, NylasEvent, NylasSchedulerBookingData } from '@/common/types';\nimport { debug } from '@/utils/utils';\nimport { AdditionalFields, Appearance, ThemeConfig, Timeslot } from '@nylas/core';\nimport { createStore } from '@stencil/store';\n\nexport type AvailabilityTimeslot = {\n emails: string[];\n start_time: Date;\n end_time: Date;\n capacity?: number;\n event_id?: string;\n master_id?: string;\n calendar_id?: string;\n};\n\nexport type LoadingState = {\n api: 'availability' | 'createBooking' | 'cancelBooking' | 'rescheduleBooking';\n};\n\nexport type ConfigSettings = {\n configuration_id: string;\n booking?: {\n additional_fields: Record<string, string>;\n additional_guests: {\n email: string;\n name: string;\n }[];\n booking_ref: string;\n booking_ref_salt: string;\n guest: {\n email: string;\n name: string;\n };\n timezone: string;\n email_language: string;\n event_data: {\n location: string;\n when: {\n start_time: Date;\n end_time: Date;\n end_timezone: string;\n start_timezone: string;\n object: string;\n };\n };\n event_organizer: {\n name: string;\n email: string;\n is_organizer: boolean;\n };\n };\n scheduler: {\n available_days_in_future: number;\n min_cancellation_notice: number;\n min_booking_notice: number;\n rescheduling_url?: string;\n cancellation_url?: string;\n cancellation_policy?: string;\n hide_additional_guests?: boolean;\n hide_cancellation_options?: boolean;\n hide_rescheduling_options?: boolean;\n additional_fields?: Record<string, AdditionalFields>;\n confirmation_redirect_url?: string;\n organizer_confirmation_url?: string;\n };\n organizer: {\n name: string;\n email: string;\n };\n slug: string;\n appearance: Appearance;\n booking_type: string;\n name: string;\n};\n\nexport interface NylasSchedulerStoreState {\n selectedDate: Date | null;\n selectedLanguage: string;\n selectedTimezone: string;\n selectedTimeslot: Timeslot | null;\n availabilityOrderEmails: string[];\n showBookingForm: boolean;\n selectableDates: Date[] | null;\n eventDuration: number;\n availability: AvailabilityTimeslot[];\n state: DataState;\n eventInfo: NylasEvent | null;\n cancelledEventInfo: Partial<NylasEvent> | null;\n reschedulingEventInfo?: NylasEvent;\n confirmedEventInfo?: NylasEvent;\n bookingInfo?: NylasSchedulerBookingData;\n rescheduleBookingId?: string;\n cancelBookingId?: string;\n isLoading: boolean;\n nylasBranding?: boolean;\n configSettings?: ConfigSettings;\n organizerConfirmationBookingId?: string;\n rejectBookingId?: string;\n organizerConfirmationSalt?: string;\n themeConfig?: ThemeConfig;\n hour12?: boolean;\n}\n\nexport type NylasSchedulerStoreType = ReturnType<typeof CreateNylasSchedulerStore>;\n\nexport function CreateNylasSchedulerStore(defaultState: Partial<NylasSchedulerStoreState> = {}) {\n const defaultNylasStoreState: NylasSchedulerStoreState = {\n selectedDate: null,\n selectedLanguage: navigator.language,\n selectedTimezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n selectedTimeslot: null,\n showBookingForm: false,\n availabilityOrderEmails: [],\n selectableDates: null,\n availability: [],\n eventDuration: 0,\n state: 'ready',\n eventInfo: null,\n cancelledEventInfo: null,\n isLoading: false,\n nylasBranding: true,\n ...defaultState,\n };\n debug(`[defaultNylasStoreState]: `, defaultNylasStoreState);\n const store = createStore<NylasSchedulerStoreState>(defaultNylasStoreState);\n\n store.onChange('availability', availability => {\n debug(`[availability]: `, availability);\n const selectableDates = availability.map(timeslot => timeslot.start_time);\n debug(`[selectableDates]: `, selectableDates);\n store.set('selectableDates', selectableDates);\n const timeslot = availability[0];\n if (!timeslot) return;\n const durationMinutes = Math.floor((timeslot.end_time.getTime() - timeslot.start_time.getTime()) / 60000);\n debug(`[durationMinutes]: `, durationMinutes);\n store.set('eventDuration', durationMinutes);\n });\n\n /**\n * Reset the Nylas store to its default state.\n * There is something wrong with the stencil/store reset method,\n * so we have to do it via this hack.\n */\n store.reset = () => {\n for (const key in defaultNylasStoreState) {\n const value = defaultNylasStoreState[key as keyof typeof defaultNylasStoreState];\n store.set(key as any, value);\n }\n };\n\n return store;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"names":["NotificationType","ErrorCategory","ComponentErrorType","Errors","constructor","this","component","_title","category","Component","title","endtime_not_in_future","message","no_booking_info","no_timeslot_selected","no_timezone_selected","no_booking_id","no_salt","invalid_start_time","invalid_end_time","invalid_timezone","no_config_id","api","Api","invalid_session","general_error","internal_error","invalid_request_error","timeslot_not_available","provider_error","not_found_error","NylaSchedulerAPIConnector","schedulerAPIURL","schedulerStore","sessionId","configId","slug","clientId","errors","getHeaders","Authorization","makeAPIRequest","path","method","body","headers","schedulerURL","URL","version","pathname","response","fetch","decodeURIComponent","toString","Origin","window","location","origin","data","json","error","type","getErrorMessage","errorMessage","setConfigId","selectDate","date","set","selectTime","time","selectTimezone","timezone","selectLanguage","language","i18next","changeLanguage","toggleAdditionalData","value","refetchAvailability","setParticipantName","name","bookingInfo","state","primaryParticipant","setParticipantEmail","email","today","Date","startTime","getFullYear","getMonth","getTime","startTimeWithOffset","Math","floor","endTime","result","getAvailability","resetStoreStateAndFetchAvailability","firstAvailableDate","get","find","timeslot","start_time","_selectedDate","setReschedule","bookingID","eventInfo","getUISettings","finally","setCancel","setReject","resetCancel","goBack","resetConfirm","undefined","bookTimeslot","selectedTimeslot","selectedTimezone","selectedLanguage","t","order","participantToBookWith","emails","addFields","Object","entries","additionalFields","forEach","key","entry","primaryGuest","guests","additional_fields","configIdParam","url","length","JSON","stringify","additional_guests","guest","end_time","event_id","master_id","calendar_id","email_language","getTwoLetterLanguageCode","shift","includes","participants","startsWith","errorType","bookingId","split","getStartTimeWithMinBookingNotice","scheduler","min_booking_notice","getEndTimeForAvailableDaysInFuture","availableDaysInFuture","available_days_in_future","endTimeForAvailableDaysInFuture","addDaysToCurrentDate","endTimeWithOffset","min","params","URLSearchParams","now","nowTime","startOfMonth","endOfMonth","startTimeWithMinBooking","append","encodeURIComponent","rescheduleBookingId","queryString","availability","time_slots","map","availabilityTimeslotsFiltered","filter","availabilityTimeslotSorted","sort","a","b","cancelBooking","reason","action","cancellation_reason","booking_id","rescheduleBooking","apiErrors","componentErrors","i","time_zone","event","updateBooking","payload","status","salt","errorTitle","validateGroupEventTimeslot","configuration_id","CreateNylasSchedulerStore","defaultState","defaultNylasStoreState","selectedDate","navigator","Intl","DateTimeFormat","resolvedOptions","timeZone","showBookingForm","availabilityOrderEmails","selectableDates","eventDuration","cancelledEventInfo","isLoading","nylasBranding","debug","store","createStore","onChange","durationMinutes","reset"],"sources":["src/types/index.ts","src/connector/nylas-scheduler-connector/errors/index.ts","src/connector/shared/api/scheduler.ts","src/stores/scheduler-store.ts"],"sourcesContent":["export interface NylasResponse<Data = any> {\n request_id: string;\n data?: Data;\n error?: {\n message: string;\n type: string;\n };\n}\n\n// Avaliability\nexport interface OpenHours {\n days: number[];\n exDates: string[];\n timezone: string;\n start: string;\n end: string;\n}\n\nexport interface MeetingBuffer {\n before: number;\n after: number;\n}\n\n// Scheduling\nexport interface UpdateConfiguration extends Omit<Configuration, 'id'> {}\n\nexport interface ParticipantAvailability {\n calendar_ids: string[];\n open_hours?: OpenHours[];\n}\n\nexport type NylasSchedulerBookingParticipant = { name: string; email: string; nameReadOnly?: boolean; emailReadOnly?: boolean };\n\nexport type NylasSchedulerBookingData = {\n primaryParticipant: NylasSchedulerBookingParticipant;\n startTime?: Date;\n endTime?: Date;\n timezone?: string;\n language?: string;\n guests?: NylasSchedulerBookingParticipant[];\n additionalFields?: Record<\n string,\n {\n value: string;\n type?: string;\n readOnly?: boolean;\n }\n >;\n};\n\nexport type OpenHour = {\n days: number[]; // [1, 2, 3, 4, 5]\n start: string; // \"09:00\"\n end: string; // \"17:00\"\n timezone: string; // \"America/Los_Angeles\"\n};\n\nexport type Timeslot = {\n start_time: Date;\n end_time: Date;\n emails?: string[];\n capacity?: number;\n event_id?: string;\n master_id?: string;\n calendar_id?: string;\n};\n\nexport type ThemeConfig = Partial<{\n '--nylas-primary': string;\n '--nylas-info': string;\n '--nylas-success': string;\n '--nylas-warning': string;\n '--nylas-error': string;\n '--nylas-error-pressed': string;\n '--nylas-base-0': string;\n '--nylas-base-25': string;\n '--nylas-base-50': string;\n '--nylas-base-100': string;\n '--nylas-base-200': string;\n '--nylas-base-300': string;\n '--nylas-base-400': string;\n '--nylas-base-500': string;\n '--nylas-base-600': string;\n '--nylas-base-700': string;\n '--nylas-base-800': string;\n '--nylas-base-900': string;\n '--nylas-base-950': string;\n '--nylas-font-family': string;\n '--nylas-font-size': string;\n '--nylas-border-radius': string;\n '--nylas-border-radius-2x': string;\n '--nylas-border-radius-3x': string;\n}>;\n\nexport enum NotificationType {\n Error = 'error',\n Warning = 'warning',\n Info = 'info',\n Success = 'success',\n}\n\nexport type Notification = {\n id: string;\n type: NotificationType;\n title: string;\n code?: number;\n category: string;\n description?: string;\n ttl?: number | 'none';\n};\n\nexport type BookingType = 'booking' | 'organizer-confirmation' | 'custom-confirmation';\n\nexport type AvailabilityMethod = 'max-fairness' | 'max-availability' | 'collective';\n\nexport type ConferenceProvider = 'GoogleMeetConferenceProvider' | 'MicrosoftTeamsConferenceProvider' | 'ZoomConferenceProvider' | 'OnlineMeetingProviderMicrosoftTeams';\n\nexport type ReminderMethod = 'email' | 'webhook';\n\nexport interface Rules {\n availability_method: AvailabilityMethod;\n buffer: MeetingBuffer;\n default_open_hours: OpenHours[];\n round_robin_group_id: string;\n}\n\nexport interface ConferenceDetail {\n meeting_code?: string; // zoom, GTM, microsoft teams\n password?: string; // zoom, webex\n url?: string; // zoom, webex, GTM, meet, microsoft teams\n pin?: string; // webex, meet\n phone?: string[]; // GTM, meet, microsoft teams\n}\n\nexport interface Conference {\n provider?: ConferenceProvider;\n details?: ConferenceDetail;\n autocreate?: { [key: string]: any };\n}\n\nexport interface ParticipantBooking {\n calendar_id: string;\n}\n\nexport interface Participant {\n email: string;\n name?: string;\n is_organizer?: boolean;\n availability?: ParticipantAvailability;\n booking?: ParticipantBooking;\n}\n\nexport interface EventReminder {\n type: ReminderMethod;\n minutes_before_event: number;\n recipient?: string;\n email_subject?: string;\n}\n\nexport interface Availability {\n duration_minutes: number;\n interval_minutes?: number;\n round_to?: number;\n availability_rules?: Rules;\n}\n\nexport interface EventBooking {\n title: string;\n description?: string;\n location?: string;\n timezone?: string;\n booking_type: BookingType;\n conferencing?: Conference;\n hide_participants?: boolean;\n disable_emails?: boolean;\n reminders?: EventReminder[];\n}\n\nexport interface Appearance {\n color?: string;\n submit_button_label?: string;\n thank_you_message?: string;\n company_logo_url?: string;\n}\n\nexport interface Scheduler {\n available_days_in_future?: number;\n min_cancellation_notice: number;\n min_booking_notice?: number;\n rescheduling_url?: string;\n cancellation_url?: string;\n organizer_confirmation_url?: string;\n cancellation_policy?: string;\n hide_additional_guests?: boolean;\n hide_cancellation_options?: boolean;\n hide_rescheduling_options?: boolean;\n additional_fields?: Record<string, AdditionalFields>;\n email_template?: EmailTemplate;\n confirmation_redirect_url?: string;\n}\nexport interface AdditionalFields {\n type: string;\n required: boolean;\n order: number;\n options?: string[];\n label?: string;\n default?: string;\n}\n\nexport interface EmailTemplate {\n logo: string;\n booking_confirmed: BookingConfirmed;\n show_nylas_branding: boolean;\n}\n\nexport interface BookingConfirmed {\n title: string;\n body: string;\n}\n\nexport interface Configuration {\n id: string;\n version: string;\n type?: string;\n requires_session_auth?: boolean;\n participants: Participant[];\n availability: Availability;\n event_booking: EventBooking;\n scheduler: Partial<Scheduler>;\n slug: string;\n appearance: Appearance;\n name: string;\n}\n\nexport interface GroupBooking {\n booking_type: BookingType; // Only 'booking' is supported\n disable_emails?: boolean;\n reminders?: EventReminder[];\n conferencing?: Conference;\n calendar_id: string;\n default_capacity: number;\n}\n\nexport interface GroupConfiguration {\n id: string;\n name: string;\n slug: string;\n requires_session_auth?: boolean;\n type: 'group';\n group_booking: GroupBooking;\n scheduler: Scheduler;\n appearance: Appearance;\n}\n\nexport interface Creator {\n name: string;\n email: string;\n}\nexport interface AdditionalParticipant {\n name: string;\n email: string;\n calendars: {\n id: string;\n name: string;\n object?: 'calendar';\n is_primary?: boolean;\n is_owned_by_user?: boolean;\n read_only?: boolean;\n timezone?: string;\n }[];\n}\n\nexport interface GroupEvent {\n id?: string;\n title: string;\n busy: boolean;\n participants: NylasSchedulerBookingParticipant[];\n resources: {\n name: string;\n email: string;\n }[];\n description: string;\n when: {\n start_time: number;\n end_time: number;\n start_timezone?: string;\n end_timezone?: string;\n };\n location: string;\n rrule: string[];\n capacity: number;\n}\n\nexport type RecurrenceUpdateOption = 'this' | 'future' | 'all';\nexport type RecurrenceDeleteOption = 'this' | 'future' | 'all';\n\nexport type Snapshot = {\n busy: boolean;\n calendar_id: string;\n hide_participants: boolean;\n ical_uid: string;\n organizer: {\n name: string;\n email: string;\n };\n participants: {\n email: string;\n status: string;\n }[];\n resources: any[];\n read_only: boolean;\n recurrence: string[];\n reminders: {\n use_default: boolean;\n overrides: any[];\n };\n title: string;\n description?: string;\n location?: string;\n conferencing?: Conference;\n visibility: string;\n creator: {\n name: string;\n email: string;\n };\n html_link: string;\n grant_id: string;\n id: string;\n object: string;\n status: string;\n when: {\n start_timezone: string;\n end_timezone: string;\n object: string;\n start_time: number; // Unix timestamp\n end_time: number; // Unix timestamp\n };\n created_at: number; // Unix timestamp\n updated_at: number; // Unix timestamp\n};\n\nexport interface GroupEventAPIData {\n event: EventDetails;\n group_event_info?: GroupEventInfo;\n}\n\nexport type EventDetails = {\n busy: boolean;\n calendar_id: string;\n conferencing: {\n provider: ConferenceProvider;\n details: {\n meeting_code: string;\n url: string;\n pin: string;\n phone: string[];\n };\n };\n hide_participants: boolean;\n ical_uid: string;\n organizer: {\n name: string;\n email: string;\n };\n participants: Array<{\n email: string;\n status: 'yes' | 'no' | 'noreply';\n comment?: string;\n }>;\n resources: string[];\n read_only: boolean;\n reminders: {\n use_default: boolean;\n overrides: Array<{\n method?: string;\n minutes?: number;\n }>;\n };\n title: string;\n description?: string;\n location?: string;\n visibility: 'default' | 'public' | 'private';\n creator: {\n name: string;\n email: string;\n };\n html_link: string;\n master_event_id: string;\n color_id: string;\n grant_id: string;\n id: string;\n object: 'event';\n status: 'confirmed' | 'tentative' | 'cancelled';\n when: {\n start_timezone: string;\n end_timezone: string;\n object: 'timespan';\n start_time: number;\n end_time: number;\n };\n created_at: number;\n updated_at: number;\n original_start_time: number;\n};\n\nexport type GroupEventInfo = {\n event_id: string;\n calendar_id: string;\n master_id: string;\n config_id: string;\n capacity: number;\n type: 'updated_event' | 'single_event' | 'master_event';\n booked: boolean;\n finished: boolean;\n participants: Array<{\n email: string;\n is_organizer: boolean;\n name: string;\n timezone: string;\n }>;\n snapshot: any | null;\n snapshot_expires_at: number;\n rrule: string[] | null;\n exceptions: {\n event_id: string;\n capacity: number;\n participants: Array<{\n email: string;\n is_organizer: boolean;\n name: string;\n timezone: string;\n }>;\n }[];\n};\n\nexport type ImportGroupEventDetails = {\n event_id: string;\n calendar_id: string;\n capacity: number;\n participants: Participant[];\n organizer: {\n name: string;\n email: string;\n };\n};\n\nexport type ImportGroupEventResponse = {\n imported_events: string[];\n import_failed: {\n event_id: string;\n reason: string;\n }[];\n};\n\nexport enum ErrorCategory {\n Component = 'component',\n Api = 'api',\n Auth = 'auth',\n}\n\nexport interface ErrorDetails {\n title: string;\n message: string;\n category: ErrorCategory;\n}\n\nexport enum ComponentErrorType {\n endtime_not_in_future = 'endtime_not_in_future',\n no_booking_info = 'no_booking_info',\n no_timeslot_selected = 'no_timeslot_selected',\n no_timezone_selected = 'no_timezone_selected',\n no_booking_id = 'no_booking_id',\n no_salt = 'no_salt',\n invalid_start_time = 'invalid_start_time',\n invalid_end_time = 'invalid_end_time',\n invalid_timezone = 'invalid_timezone',\n no_config_id = 'no_config_id',\n}\n\nexport interface KeyPoint {\n time: number;\n text: string;\n active?: boolean;\n}\n","import { ComponentErrorType, ErrorCategory, ErrorDetails } from '@/types/index';\nimport { APIErrorType } from '@nylas/core';\nexport class Errors {\n component = (_title: string): Record<ComponentErrorType, (message?: string) => ErrorDetails> => {\n const category = ErrorCategory.Component;\n const title = `${_title} Error`;\n return {\n endtime_not_in_future: (message: string = '\"endtime\" can not be in the future') => {\n return {\n title,\n message,\n category,\n };\n },\n no_booking_info: (message: string = 'No booking info provided') => {\n return {\n title,\n message,\n category,\n };\n },\n no_timeslot_selected: (message: string = 'No timeslot selected') => {\n return {\n title,\n message,\n category,\n };\n },\n no_timezone_selected: (message: string = 'No timezone selected') => {\n return {\n title,\n message,\n category,\n };\n },\n no_booking_id: (message: string = 'No booking id provided') => {\n return {\n title,\n message,\n category,\n };\n },\n no_salt: (message: string = 'No salt provided') => {\n return {\n title,\n message,\n category,\n };\n },\n invalid_start_time: (message: string = 'Invalid start time') => {\n return {\n title,\n message,\n category,\n };\n },\n invalid_end_time: (message: string = 'Invalid end time') => {\n return {\n title,\n message,\n category,\n };\n },\n invalid_timezone: (message: string = 'Invalid timezone') => {\n return {\n title,\n message,\n category,\n };\n },\n no_config_id: (message: string = 'No configuration id provided') => {\n return {\n title,\n message,\n category,\n };\n },\n };\n };\n\n api = (_title: string): Record<APIErrorType, (message: string) => ErrorDetails> => {\n const category = ErrorCategory.Api;\n const title = `${_title} Error`;\n\n return {\n invalid_session: (message: string) => {\n return {\n title,\n message,\n category,\n };\n },\n general_error: (message: string) => {\n return {\n title,\n message,\n category,\n };\n },\n internal_error: (message: string) => {\n return {\n title,\n message,\n category,\n };\n },\n invalid_request_error: (message: string) => {\n return {\n title,\n message,\n category,\n };\n },\n timeslot_not_available: (message: string) => {\n return {\n title,\n message,\n category,\n };\n },\n provider_error: (message: string) => {\n return {\n title,\n message,\n category,\n };\n },\n not_found_error: (message: string) => {\n return {\n title,\n message,\n category,\n };\n },\n };\n };\n}\n","import { AvailabilityResponse, NylasSchedulerBookingData, NylasSchedulerBookingDataWithFlatFields, NylasEvent, UISettingsResponse } from '@/common/types';\nimport { NylasSchedulerStoreType } from '../../../components';\nimport type { NylasErrorResponse, NylasResponse, NylasSchedulerResponse, Timeslot } from '@nylas/core';\nimport { Errors } from '@/connector/nylas-scheduler-connector/errors';\nimport { addDaysToCurrentDate } from '@/utils/utils';\nimport i18next from '@/utils/i18n';\nimport { APIErrorType } from '@nylas/core';\n\ntype NylasSchedulerAPIConnectorOptions = {\n schedulerAPIURL: string;\n schedulerStore: NylasSchedulerStoreType;\n sessionId?: string;\n configId?: string;\n slug?: string;\n clientId?: string;\n};\n\n/**\n * NylaSchedulerConnector\n * This class is used to make API requests to the scheduler.\n */\nexport class NylaSchedulerAPIConnector {\n private schedulerStore: NylasSchedulerStoreType;\n private schedulerAPIURL: string;\n private sessionId: string | undefined;\n private configId: string | undefined;\n private slug: string | undefined;\n private clientId: string | undefined;\n private errors = new Errors();\n\n constructor({ schedulerAPIURL, schedulerStore, sessionId, configId, slug, clientId }: NylasSchedulerAPIConnectorOptions) {\n this.schedulerStore = schedulerStore;\n this.schedulerAPIURL = schedulerAPIURL;\n this.sessionId = sessionId;\n this.configId = configId;\n this.slug = slug;\n this.clientId = clientId;\n }\n\n private getHeaders() {\n return this.sessionId\n ? {\n Authorization: `Bearer ${this.sessionId}`,\n }\n : {};\n }\n\n /**\n * Makes an API request to the scheduler.\n * @param path The path to the API endpoint.\n * @param method The HTTP method.\n * @param body The request body (if any).\n * @returns {Promise<T>}\n */\n public async makeAPIRequest<T>(path: string, method: string, body: string | undefined, headers = {}): Promise<NylasResponse<T>> {\n try {\n const schedulerURL = new URL(this.schedulerAPIURL);\n const version = process.env.PACKAGE_VERSION || 'latest';\n schedulerURL.pathname = path;\n const response = await fetch(decodeURIComponent(schedulerURL.toString()), {\n method,\n headers: {\n 'Content-Type': 'application/json',\n 'Origin': window.location.origin,\n 'X-Source': 'nylas-scheduling',\n 'X-Nylas-Web-Elements-Version': version,\n ...headers,\n },\n body,\n });\n // The server returns a json object for errors: eg.\n // {\n // \"request_id\": \"<request_id>\",\n // \"error\": {\n // \"type\": \"not_found_error\",\n // \"message\": \"Session not found\"\n // }\n // }\n const data = await response.json();\n return data as NylasResponse<T>;\n } catch (error: any) {\n // NOTE: current server implementation doesn't return a JSON object for errors on some endpoints\n // handle this case by returning the error response as a string to be handled downstream\n return {\n error: {\n message: error.message,\n title: 'API request failed',\n type: 'api',\n },\n } as NylasErrorResponse;\n }\n }\n\n private getErrorMessage(error: NylasErrorResponse['error']) {\n let errorMessage = error?.message || error?.title || 'Something went wrong';\n if (error?.type === 'provider_error') {\n errorMessage = error?.provider_error?.error?.message || error?.provider_error?.error?.title || 'Something went wrong';\n }\n return errorMessage;\n }\n\n public setConfigId(configId: string) {\n this.configId = configId;\n }\n\n /**\n * Selects a date in the scheduler.\n */\n public selectDate(date: Date) {\n this.schedulerStore.set('selectedDate', date);\n this.schedulerStore.set('selectedTimeslot', null);\n }\n\n /**\n * Selects a time in the scheduler.\n */\n public selectTime(time: Timeslot) {\n this.schedulerStore.set('selectedTimeslot', time);\n }\n\n /**\n * Sets the timezone in the scheduler.\n */\n public selectTimezone(timezone: string) {\n this.schedulerStore.set('selectedTimezone', timezone);\n }\n\n /**\n * Sets the language in the scheduler.\n */\n public selectLanguage(language: string) {\n this.schedulerStore.set('selectedLanguage', language);\n i18next.changeLanguage(language);\n }\n\n /**\n * Toggles showBookingForm\n * @param value boolean\n */\n public async toggleAdditionalData(value: boolean) {\n if (!value) {\n // Refetch availability\n await this.refetchAvailability();\n }\n this.schedulerStore.set('showBookingForm', value);\n }\n\n /**\n * Set/update the name of the participant booking the event.\n */\n public setParticipantName(name: string) {\n const { bookingInfo } = this.schedulerStore.state;\n this.schedulerStore.set('bookingInfo', {\n ...bookingInfo,\n primaryParticipant: {\n ...(bookingInfo?.primaryParticipant as NylasSchedulerBookingData['primaryParticipant']),\n name,\n },\n });\n }\n\n /**\n * Set/update the email of the participant booking the event.\n */\n public setParticipantEmail(email: string) {\n const { bookingInfo } = this.schedulerStore.state;\n this.schedulerStore.set('bookingInfo', {\n ...bookingInfo,\n primaryParticipant: {\n ...(bookingInfo?.primaryParticipant as NylasSchedulerBookingData['primaryParticipant']),\n email,\n },\n });\n }\n\n private async refetchAvailability() {\n const today = new Date();\n // Refetch availability\n const startTime = new Date(today.getFullYear(), today.getMonth(), 1).getTime() / 1000;\n const startTimeWithOffset = startTime < today.getTime() / 1000 ? Math.floor(today.getTime() / 1000) : startTime;\n const endTime = new Date(today.getFullYear(), today.getMonth() + 1, 1).getTime() / 1000;\n const result = await this.getAvailability(startTimeWithOffset, endTime);\n return result;\n }\n\n private async resetStoreStateAndFetchAvailability() {\n const today = new Date();\n // Refetch availability\n const result = await this.refetchAvailability();\n // Set selected date to first available date\n const firstAvailableDate = this.schedulerStore.get('availability').find((timeslot: any) => new Date(timeslot.start_time) > new Date());\n let _selectedDate = today;\n if (firstAvailableDate) {\n _selectedDate = firstAvailableDate.start_time;\n }\n this.schedulerStore.set('selectedDate', _selectedDate);\n // Reset store state\n this.schedulerStore.set('eventInfo', null);\n this.schedulerStore.set('showBookingForm', false);\n this.schedulerStore.set('selectedTimeslot', null);\n\n return result;\n }\n\n /**\n * Set reschedule booking id\n */\n public async setReschedule(bookingID: string) {\n this.schedulerStore.set('isLoading', true);\n const eventInfo = this.schedulerStore.state.eventInfo;\n if (eventInfo) {\n this.schedulerStore.set('reschedulingEventInfo', eventInfo);\n }\n this.schedulerStore.set('rescheduleBookingId', bookingID);\n await this.getUISettings();\n // Set reschedule booking id\n const result = await this.resetStoreStateAndFetchAvailability().finally(() => {\n this.schedulerStore.set('isLoading', false);\n });\n\n return result;\n }\n\n /**\n * Set cancel booking id\n */\n public async setCancel(bookingID: string) {\n this.schedulerStore.set('cancelBookingId', bookingID);\n }\n\n /**\n * Set reject booking id\n */\n public async setReject(bookingID: string) {\n this.schedulerStore.set('rejectBookingId', bookingID);\n }\n\n public async resetCancel() {\n const result = await this.resetStoreStateAndFetchAvailability();\n this.schedulerStore.set('cancelBookingId', '');\n this.schedulerStore.set('rejectBookingId', '');\n this.schedulerStore.set('cancelledEventInfo', null);\n return result;\n }\n\n public async goBack() {\n this.schedulerStore.set('cancelBookingId', '');\n return;\n }\n\n public async resetConfirm() {\n const result = await this.resetStoreStateAndFetchAvailability();\n this.schedulerStore.set('organizerConfirmationBookingId', '');\n this.schedulerStore.set('confirmedEventInfo', undefined);\n return result;\n }\n\n /**\n * Book the selected timeslot.\n * @param data The booking info.\n * @returns {Promise<NylasResponse<NylasEvent>>}\n */\n public async bookTimeslot(data?: NylasSchedulerBookingDataWithFlatFields & { timeslot?: Timeslot }): Promise<NylasSchedulerResponse<NylasEvent>> {\n this.schedulerStore.set('isLoading', true);\n const { selectedTimeslot, selectedTimezone, bookingInfo, selectedLanguage } = this.schedulerStore.state;\n\n if (!data && !bookingInfo) {\n return { error: this.errors.component(i18next.t('createBookingErrorTitle')).no_booking_info() };\n }\n\n const timeslot = data?.timeslot || selectedTimeslot;\n if (!timeslot) {\n return { error: this.errors.component(i18next.t('createBookingErrorTitle')).no_timeslot_selected() };\n }\n\n const timezone = data && data?.timezone ? data?.timezone : selectedTimezone;\n const language = selectedLanguage || 'en-US';\n\n if (!timezone) {\n return { error: this.errors.component(i18next.t('createBookingErrorTitle')).no_timezone_selected() };\n }\n\n const order = [...this.schedulerStore.get('availabilityOrderEmails')];\n\n let participantToBookWith = '';\n const emails = timeslot?.emails || [];\n\n const addFields = {};\n Object.entries(bookingInfo?.additionalFields || {}).forEach(([key, entry]) => {\n addFields[key] = (entry as { value: string; type?: string }).value;\n });\n\n const primaryGuest = data ? data?.primaryParticipant : bookingInfo?.primaryParticipant;\n const guests = data ? data?.guests || [] : bookingInfo?.guests || [];\n const additional_fields = data ? data?.additionalFields : addFields;\n\n const headers = this.getHeaders();\n const configIdParam =\n !this.sessionId && this.configId\n ? `?configuration_id=${this.configId}`\n : !this.sessionId && this.slug && this.clientId\n ? `?slug=${this.slug}&client_id=${this.clientId}`\n : '';\n const url = `/v3/scheduling/bookings${configIdParam}`;\n\n // If the order array is empty, make a single request without retries\n if (order.length === 0) {\n const response = await this.makeAPIRequest<NylasEvent>(\n decodeURIComponent(url),\n 'POST',\n JSON.stringify({\n additional_fields,\n additional_guests: guests,\n guest: { ...primaryGuest },\n start_time: timeslot.start_time.getTime() / 1000,\n end_time: timeslot.end_time.getTime() / 1000,\n timezone,\n event_id: timeslot?.event_id || undefined,\n master_id: timeslot?.master_id || undefined,\n calendar_id: timeslot?.calendar_id || undefined,\n email_language: this.getTwoLetterLanguageCode(language),\n }),\n headers,\n );\n\n this.schedulerStore.set('isLoading', false);\n if ('data' in response) {\n this.schedulerStore.set('eventInfo', response.data);\n return response;\n }\n return { error: response.error };\n }\n\n while (order.length > 0) {\n participantToBookWith = order.shift()!;\n\n if (!emails.includes(participantToBookWith)) {\n continue; // Skip if the email is not part of the timeslot\n }\n\n const response = await this.makeAPIRequest<NylasEvent>(\n decodeURIComponent(url),\n 'POST',\n JSON.stringify({\n participants: participantToBookWith ? [{ email: participantToBookWith }] : undefined,\n additional_fields,\n additional_guests: guests,\n guest: { ...primaryGuest },\n start_time: timeslot.start_time.getTime() / 1000,\n end_time: timeslot.end_time.getTime() / 1000,\n timezone: timezone,\n email_language: this.getTwoLetterLanguageCode(language),\n }),\n headers,\n );\n\n if ('data' in response) {\n // Successful booking\n this.schedulerStore.set('isLoading', false);\n this.schedulerStore.set('eventInfo', response?.data);\n return response;\n } else if (response.error?.message?.startsWith('The selected timeslot is unavailable')) {\n // Retry with the next email in the order\n continue;\n } else {\n // Return other errors\n this.schedulerStore.set('isLoading', false);\n const errorType = response.error?.type;\n let error = response.error;\n if (errorType && errorType in this.errors.api(i18next.t('createBookingErrorTitle'))) {\n const errorMessage = this.getErrorMessage(error);\n error = this.errors.api(i18next.t('createBookingErrorTitle'))[errorType as APIErrorType](errorMessage);\n }\n return { error };\n }\n }\n\n // If no emails in order succeed\n this.schedulerStore.set('isLoading', false);\n return {\n error: this.errors.api(i18next.t('createBookingErrorTitle')).timeslot_not_available('The selected timeslot is unavailable'),\n };\n }\n\n /**\n * Get UI settings for the scheduler.\n */\n public async getUISettings(): Promise<NylasSchedulerResponse<UISettingsResponse>> {\n this.schedulerStore.set('isLoading', true);\n const bookingId = this.schedulerStore.get('rescheduleBookingId');\n const headers = this.getHeaders();\n let configIdParam =\n !this.sessionId && this.configId\n ? `?configuration_id=${this.configId}`\n : !this.sessionId && this.slug && this.clientId\n ? `?slug=${this.slug}&client_id=${this.clientId}`\n : '';\n if (bookingId && !!configIdParam) {\n configIdParam += `&booking_id=${bookingId}`;\n } else if (bookingId) {\n configIdParam += `?booking_id=${bookingId}`;\n }\n\n const url = `/v3/scheduling/ui-settings${configIdParam}`;\n\n const response = await this.makeAPIRequest<UISettingsResponse>(url, 'GET', undefined, headers);\n if ('error' in response) {\n this.schedulerStore.set('isLoading', false);\n const errorType = response.error?.type;\n let error = response.error;\n if (errorType && errorType in this.errors.api(i18next.t('getUISettingErrorTitle'))) {\n error = this.errors.api(i18next.t('getUISettingErrorTitle'))[errorType as APIErrorType](error?.message || error?.title || 'Something went wrong');\n }\n return { error };\n }\n if ('data' in response) {\n this.schedulerStore.set('configSettings', response.data);\n }\n this.schedulerStore.set('isLoading', false);\n return response;\n }\n\n private getTwoLetterLanguageCode(language: string) {\n return language.split('-')[0];\n }\n\n private getStartTimeWithMinBookingNotice(startTime: number) {\n const scheduler = this.schedulerStore.get('configSettings')?.scheduler;\n const min_booking_notice = scheduler?.min_booking_notice;\n if (!min_booking_notice) {\n return startTime;\n }\n const today = new Date().getTime();\n\n if (startTime < (today + min_booking_notice * 60 * 1000) / 1000) {\n return Math.floor((today + min_booking_notice * 60 * 1000) / 1000);\n } else {\n return startTime;\n }\n }\n\n private getEndTimeForAvailableDaysInFuture(endTime: number) {\n const today = new Date();\n const availableDaysInFuture = this.schedulerStore.get('configSettings')?.scheduler?.available_days_in_future;\n const endTimeForAvailableDaysInFuture = Math.floor(addDaysToCurrentDate(today, availableDaysInFuture).getTime() / 1000);\n const endTimeWithOffset = Math.min(endTimeForAvailableDaysInFuture, endTime);\n return endTimeWithOffset;\n }\n\n /**\n * Gets the availability for a page.\n * @param startTime The start time.\n * @param endTime The end time.\n * @returns {Promise<AvailabilityResponse>}\n */\n public async getAvailability(startTime: number = 0, endTime: number = 0): Promise<NylasSchedulerResponse<AvailabilityResponse>> {\n this.schedulerStore.set('isLoading', true);\n const params = new URLSearchParams();\n const now = new Date();\n const nowTime = now.getTime();\n\n if (endTime && endTime < nowTime / 1000) {\n this.schedulerStore.set('isLoading', false);\n const error = this.errors.component(i18next.t('getAvailabilityErrorTitle')).endtime_not_in_future();\n return { error };\n }\n\n // Calculate the start of the current month if startTime is not provided\n if (!startTime) {\n const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);\n startTime = Math.floor(startOfMonth.getTime() / 1000); // Convert to UNIX timestamp in seconds\n }\n\n // Calculate the end of the current month if endTime is not provided\n if (!endTime) {\n const endOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 0); // Setting day to 0 gets the last day of the previous month, so in this case, the last day of the current month\n endTime = Math.floor(endOfMonth.getTime() / 1000); // Convert to UNIX timestamp in seconds\n }\n\n endTime = this.getEndTimeForAvailableDaysInFuture(endTime);\n const startTimeWithMinBooking = this.getStartTimeWithMinBookingNotice(startTime);\n startTime = startTimeWithMinBooking;\n endTime = startTimeWithMinBooking > endTime ? startTimeWithMinBooking + 1 : endTime;\n\n params.append('start_time', encodeURIComponent(startTime.toString()));\n params.append('end_time', encodeURIComponent(endTime.toString()));\n if (this.configId && !this.sessionId) {\n params.append('configuration_id', encodeURIComponent(this.configId));\n } else if (this.slug && this.clientId && !this.sessionId) {\n params.append('slug', encodeURIComponent(this.slug));\n params.append('client_id', encodeURIComponent(this.clientId));\n }\n\n const rescheduleBookingId = this.schedulerStore.get('rescheduleBookingId');\n if (rescheduleBookingId) {\n params.append('booking_id', encodeURIComponent(rescheduleBookingId));\n }\n const queryString = params.toString();\n const url = `/v3/scheduling/availability${queryString ? `?${queryString}` : ''}`;\n const headers = this.getHeaders();\n const response = await this.makeAPIRequest<AvailabilityResponse>(decodeURIComponent(url), 'GET', undefined, headers);\n\n if ('error' in response) {\n this.schedulerStore.set('availability', []);\n this.schedulerStore.set('isLoading', false);\n const errorType = response.error?.type;\n let error = response.error;\n if (errorType && errorType in this.errors.api(i18next.t('getAvailabilityErrorTitle'))) {\n const errorMessage = this.getErrorMessage(error);\n error = this.errors.api(i18next.t('getAvailabilityErrorTitle'))[errorType as APIErrorType](errorMessage);\n }\n return { error };\n }\n\n if ('data' in response) {\n const availability =\n response.data?.time_slots?.map(timeslot => {\n return {\n ...timeslot,\n start_time: new Date(timeslot.start_time * 1000),\n end_time: new Date(timeslot.end_time * 1000),\n };\n }) || [];\n\n // Filter out timeslots that are in the past\n const availabilityTimeslotsFiltered = availability.filter(timeslot => timeslot.start_time.getTime() > nowTime);\n const availabilityTimeslotSorted = availabilityTimeslotsFiltered.sort((a, b) => a.start_time.getTime() - b.start_time.getTime());\n this.schedulerStore.set('availability', availabilityTimeslotSorted);\n const order = response.data?.order || [];\n this.schedulerStore.set('availabilityOrderEmails', order);\n }\n\n this.schedulerStore.set('isLoading', false);\n return response;\n }\n\n /**\n * Cancels a booking.\n * @param bookingId The booking ID.\n */\n public async cancelBooking(bookingId: string, reason: string): Promise<NylasSchedulerResponse<Partial<NylasEvent>>> {\n this.schedulerStore.set('isLoading', true);\n if (!bookingId) {\n return { error: this.errors.component(i18next.t('cancelBookingErrorTitle')).no_booking_id() };\n }\n const configIdParam =\n !this.sessionId && this.configId\n ? `?configuration_id=${this.configId}`\n : !this.sessionId && this.slug && this.clientId\n ? `?slug=${this.slug}&client_id=${this.clientId}`\n : '';\n const url = `/v3/scheduling/bookings/${bookingId}${configIdParam}`;\n const headers = this.getHeaders();\n const response = await this.makeAPIRequest<Partial<NylasEvent>>(\n decodeURIComponent(url),\n 'DELETE',\n JSON.stringify({\n action: 'cancel',\n cancellation_reason: reason,\n }),\n headers,\n );\n\n if ('error' in response) {\n this.schedulerStore.set('isLoading', false);\n const errorType = response.error?.type;\n let error = response.error;\n if (errorType && errorType in this.errors.api(i18next.t('cancelBookingErrorTitle'))) {\n const errorMessage = this.getErrorMessage(error);\n error = this.errors.api(i18next.t('cancelBookingErrorTitle'))[errorType as APIErrorType](errorMessage);\n }\n return { error };\n }\n\n this.schedulerStore.set('cancelledEventInfo', {\n booking_id: bookingId,\n });\n this.schedulerStore.set('rescheduleBookingId', '');\n this.schedulerStore.set('isLoading', false);\n return response;\n }\n\n /**\n * Reschedules a booking.\n * @param bookingId The booking ID.\n * @param data The booking info.\n * @returns {Promise<NylasResponse<NylasEvent>>}\n */\n public async rescheduleBooking(bookingId: string, data: NylasSchedulerBookingDataWithFlatFields): Promise<NylasSchedulerResponse<NylasEvent>> {\n this.schedulerStore.set('isLoading', true);\n if (!bookingId) {\n return { error: this.errors.component(i18next.t('rescheduleBookingErrorTitle')).no_booking_id() };\n }\n const apiErrors = this.errors.api(i18next.t('rescheduleBookingErrorTitle'));\n const componentErrors = this.errors.component(i18next.t('rescheduleBookingErrorTitle'));\n const { bookingInfo, selectedTimeslot, selectedTimezone, selectedLanguage } = this.schedulerStore.state;\n // Validate data\n const { startTime, endTime, timezone } = data;\n const start_time = startTime || selectedTimeslot?.start_time;\n\n if (!start_time) {\n return { error: componentErrors.invalid_start_time('Please pass \"startTime\" in data or set \"selectedTimeslot\" in the defaultSchedulerState.') };\n }\n const end_time = endTime || selectedTimeslot?.end_time;\n if (!end_time) {\n return { error: componentErrors.invalid_end_time('Please pass \"endTime\" in data or set \"selectedTimeslot\" in the defaultSchedulerState.') };\n }\n\n const order = this.schedulerStore.get('availabilityOrderEmails');\n let participantToBookWith = '';\n if (order.length > 0) {\n // Get the emails in the timeslot\n const emails = selectedTimeslot?.emails || [];\n for (let i = 0; i < order.length; i++) {\n if (emails.includes(order[i])) {\n participantToBookWith = order[i];\n break;\n }\n }\n }\n\n const time_zone = timezone || selectedTimezone;\n if (!time_zone) {\n return { error: componentErrors.invalid_timezone('Please pass \"timezone\" in data or set \"selectedTimezone\" in the defaultSchedulerState.') };\n }\n const addFields = {};\n Object.entries(bookingInfo?.additionalFields || {}).forEach(([key, entry]) => {\n addFields[key] = (entry as { value: string; type?: string }).value;\n });\n const primaryGuest = data ? data?.primaryParticipant : bookingInfo?.primaryParticipant;\n const guests = data ? data?.guests || [] : bookingInfo?.guests || [];\n const additional_fields = data ? data?.additionalFields : addFields;\n\n const configIdParam =\n !this.sessionId && this.configId\n ? `?configuration_id=${this.configId}`\n : !this.sessionId && this.slug && this.clientId\n ? `?slug=${this.slug}&client_id=${this.clientId}`\n : '';\n const url = `/v3/scheduling/bookings/${bookingId}${configIdParam}`;\n const headers = this.getHeaders();\n const response = await this.makeAPIRequest<NylasEvent>(\n decodeURIComponent(url),\n 'PATCH',\n JSON.stringify({\n start_time: start_time.getTime() / 1000,\n end_time: end_time.getTime() / 1000,\n timezone: time_zone,\n additional_fields,\n guest: { ...primaryGuest },\n additional_guests: guests,\n participants: participantToBookWith ? [{ email: participantToBookWith }] : undefined,\n email_language: this.getTwoLetterLanguageCode(selectedLanguage),\n }),\n headers,\n );\n\n if ('error' in response) {\n this.schedulerStore.set('isLoading', false);\n const errorType = response.error?.type;\n let error = response.error;\n if (errorType && errorType in apiErrors) {\n const errorMessage = this.getErrorMessage(error);\n error = apiErrors[errorType as APIErrorType](errorMessage);\n }\n return { error };\n }\n\n const eventInfo = this.schedulerStore.get('reschedulingEventInfo');\n if ('data' in response) {\n this.schedulerStore.set('eventInfo', response?.data);\n } else if (eventInfo) {\n this.schedulerStore.set('eventInfo', eventInfo);\n } else {\n // We should technically never reach this point\n const event = {\n booking_id: bookingId,\n } as NylasEvent;\n this.schedulerStore.set('eventInfo', event);\n }\n\n this.schedulerStore.set('isLoading', false);\n return response;\n }\n\n /**\n * Updates the booking.\n * @param bookingId The booking ID.\n */\n public async updateBooking(payload: { bookingId: string; status: 'confirmed' | 'cancelled'; reason?: string }): Promise<NylasSchedulerResponse<NylasEvent>> {\n this.schedulerStore.set('isLoading', true);\n const { bookingId, status, reason } = payload;\n const salt = this.schedulerStore.get('organizerConfirmationSalt');\n const errorTitle = status === 'confirmed' ? i18next.t('confirmBookingErrorTitle') : i18next.t('rejectBookingErrorTitle');\n\n if (!bookingId) {\n return { error: this.errors.component(errorTitle).no_booking_id() };\n }\n if (!salt) {\n return { error: this.errors.component(errorTitle).no_salt() };\n }\n\n const configIdParam =\n !this.sessionId && this.configId\n ? `?configuration_id=${this.configId}`\n : !this.sessionId && this.slug && this.clientId\n ? `?slug=${this.slug}&client_id=${this.clientId}`\n : '';\n const url = `/v3/scheduling/bookings/${bookingId}${configIdParam}`;\n const headers = this.getHeaders();\n const response = await this.makeAPIRequest<NylasEvent>(\n decodeURIComponent(url),\n 'PUT',\n JSON.stringify({\n status: status,\n cancellation_reason: reason,\n salt,\n }),\n headers,\n );\n\n if ('error' in response) {\n this.schedulerStore.set('isLoading', false);\n const errorType = response.error?.type;\n let error = response.error;\n if (errorType && errorType in this.errors.api(errorTitle)) {\n const errorMessage = this.getErrorMessage(error);\n error = this.errors.api(errorTitle)[errorType as APIErrorType](errorMessage);\n }\n return { error };\n }\n\n if ('data' in response && status === 'confirmed') {\n this.schedulerStore.set('confirmedEventInfo', response?.data);\n } else if ('request_id' in response && status === 'cancelled') {\n this.schedulerStore.set('cancelledEventInfo', {\n booking_id: bookingId,\n });\n }\n\n this.schedulerStore.set('organizerConfirmationBookingId', '');\n this.schedulerStore.set('isLoading', false);\n return response;\n }\n\n /**\n * Validate timeslot for group event booking\n */\n public async validateGroupEventTimeslot(timeslot: Timeslot) {\n this.schedulerStore.set('isLoading', true);\n const configId = this.schedulerStore.get('configSettings')?.configuration_id;\n if (!configId) {\n return { error: this.errors.component(i18next.t('validateTimeslotErrorTitle')).no_config_id() };\n }\n\n const headers = this.getHeaders();\n const url = `/v3/scheduling/configurations/${configId}/group-events/validate-timeslot`;\n const response = await this.makeAPIRequest<NylasEvent>(\n decodeURIComponent(url),\n 'POST',\n JSON.stringify({\n ...timeslot,\n start_time: timeslot.start_time.getTime() / 1000,\n end_time: timeslot.end_time.getTime() / 1000,\n }),\n headers,\n );\n\n if ('error' in response) {\n this.schedulerStore.set('isLoading', false);\n const errorType = response.error?.type;\n let error = response.error;\n if (errorType && errorType in this.errors.api(i18next.t('validateTimeslotErrorTitle'))) {\n const errorMessage = this.getErrorMessage(error);\n error = this.errors.api(i18next.t('validateTimeslotErrorTitle'))[errorType as APIErrorType](errorMessage);\n }\n this.refetchAvailability();\n return { error };\n }\n\n this.schedulerStore.set('selectedTimeslot', timeslot);\n this.schedulerStore.set('showBookingForm', true);\n this.schedulerStore.set('isLoading', false);\n return response;\n }\n}\n","import { DataState, NylasEvent, NylasSchedulerBookingData } from '@/common/types';\nimport { debug } from '@/utils/utils';\nimport { AdditionalFields, Appearance, ThemeConfig, Timeslot } from '@nylas/core';\nimport { createStore } from '@stencil/store';\n\nexport type AvailabilityTimeslot = {\n emails: string[];\n start_time: Date;\n end_time: Date;\n capacity?: number;\n event_id?: string;\n master_id?: string;\n calendar_id?: string;\n};\n\nexport type LoadingState = {\n api: 'availability' | 'createBooking' | 'cancelBooking' | 'rescheduleBooking';\n};\n\nexport type ConfigSettings = {\n configuration_id: string;\n booking?: {\n additional_fields: Record<string, string>;\n additional_guests: {\n email: string;\n name: string;\n }[];\n booking_ref: string;\n booking_ref_salt: string;\n guest: {\n email: string;\n name: string;\n };\n timezone: string;\n email_language: string;\n event_data: {\n location: string;\n when: {\n start_time: Date;\n end_time: Date;\n end_timezone: string;\n start_timezone: string;\n object: string;\n };\n };\n event_organizer: {\n name: string;\n email: string;\n is_organizer: boolean;\n };\n };\n scheduler: {\n available_days_in_future: number;\n min_cancellation_notice: number;\n min_booking_notice: number;\n rescheduling_url?: string;\n cancellation_url?: string;\n cancellation_policy?: string;\n hide_additional_guests?: boolean;\n hide_cancellation_options?: boolean;\n hide_rescheduling_options?: boolean;\n additional_fields?: Record<string, AdditionalFields>;\n confirmation_redirect_url?: string;\n organizer_confirmation_url?: string;\n };\n organizer: {\n name: string;\n email: string;\n };\n slug: string;\n appearance: Appearance;\n booking_type: string;\n name: string;\n};\n\nexport interface NylasSchedulerStoreState {\n selectedDate: Date | null;\n selectedLanguage: string;\n selectedTimezone: string;\n selectedTimeslot: Timeslot | null;\n availabilityOrderEmails: string[];\n showBookingForm: boolean;\n selectableDates: Date[] | null;\n eventDuration: number;\n availability: AvailabilityTimeslot[];\n state: DataState;\n eventInfo: NylasEvent | null;\n cancelledEventInfo: Partial<NylasEvent> | null;\n reschedulingEventInfo?: NylasEvent;\n confirmedEventInfo?: NylasEvent;\n bookingInfo?: NylasSchedulerBookingData;\n rescheduleBookingId?: string;\n cancelBookingId?: string;\n isLoading: boolean;\n nylasBranding?: boolean;\n configSettings?: ConfigSettings;\n organizerConfirmationBookingId?: string;\n rejectBookingId?: string;\n organizerConfirmationSalt?: string;\n themeConfig?: ThemeConfig;\n hour12?: boolean;\n}\n\nexport type NylasSchedulerStoreType = ReturnType<typeof CreateNylasSchedulerStore>;\n\nexport function CreateNylasSchedulerStore(defaultState: Partial<NylasSchedulerStoreState> = {}) {\n const defaultNylasStoreState: NylasSchedulerStoreState = {\n selectedDate: null,\n selectedLanguage: navigator.language,\n selectedTimezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n selectedTimeslot: null,\n showBookingForm: false,\n availabilityOrderEmails: [],\n selectableDates: null,\n availability: [],\n eventDuration: 0,\n state: 'ready',\n eventInfo: null,\n cancelledEventInfo: null,\n isLoading: false,\n nylasBranding: true,\n ...defaultState,\n };\n debug(`[defaultNylasStoreState]: `, defaultNylasStoreState);\n const store = createStore<NylasSchedulerStoreState>(defaultNylasStoreState);\n\n store.onChange('availability', availability => {\n debug(`[availability]: `, availability);\n const selectableDates = availability.map(timeslot => timeslot.start_time);\n debug(`[selectableDates]: `, selectableDates);\n store.set('selectableDates', selectableDates);\n const timeslot = availability[0];\n if (!timeslot) return;\n const durationMinutes = Math.floor((timeslot.end_time.getTime() - timeslot.start_time.getTime()) / 60000);\n debug(`[durationMinutes]: `, durationMinutes);\n store.set('eventDuration', durationMinutes);\n });\n\n /**\n * Reset the Nylas store to its default state.\n * There is something wrong with the stencil/store reset method,\n * so we have to do it via this hack.\n */\n store.reset = () => {\n for (const key in defaultNylasStoreState) {\n const value = defaultNylasStoreState[key as keyof typeof defaultNylasStoreState];\n store.set(key as any, value);\n }\n };\n\n return store;\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import{h as t,r,a as s}from"./p-6f5a3998.js";import{a,u as
|
|
2
|
-
//# sourceMappingURL=p-
|
|
1
|
+
import{h as t,r,a as s}from"./p-6f5a3998.js";import{a,u as n}from"./p-c79dcb59.js";import{v as e}from"./p-890d7f01.js";import{c as i}from"./p-fc5bc07b.js";const o=new CSSStyleSheet;o.replaceSync(`\n :host {\n font-family: Arial, sans-serif;\n }\n`);const c=i({style:o,toolbarState:"default",searchTerm:""});const l=({width:r,height:s,fill:a})=>t("svg",{viewBox:"0 0 16 16",width:r,height:s,xmlns:"http://www.w3.org/2000/svg"},t("path",{d:"M9.30887 10.016C8.53903 10.6318 7.56252 11 6.5 11C4.01472 11 2 8.98531 2 6.50002C2 4.01473 4.01472 2 6.5 2C8.98528 2 11 4.01473 11 6.50002C11 7.56252 10.6318 8.53901 10.016 9.30885L13.8536 13.1464C14.0488 13.3417 14.0488 13.6583 13.8536 13.8536C13.6583 14.0488 13.3417 14.0488 13.1464 13.8536L9.30887 10.016ZM10 6.50002C10 4.56701 8.433 3 6.5 3C4.567 3 3 4.56701 3 6.50002C3 8.43302 4.567 10 6.5 10C8.433 10 10 8.43302 10 6.50002Z",fill:a}));const p=({width:r,height:s,fill:a,className:n})=>t("svg",{width:r,height:s,class:n,viewBox:"0 0 16 16",xmlns:"http://www.w3.org/2000/svg"},t("path",{d:"M4.00029 4.08525L4 10.5C4 11.8255 5.03154 12.91 6.33562 12.9947L6.5 13L10.9144 13.0007C10.7083 13.5829 10.1528 14 9.5 14H6C4.34315 14 3 12.6569 3 11V5.5C3 4.84678 3.41754 4.29109 4.00029 4.08525ZM11.5 2C12.3284 2 13 2.67157 13 3.5V10.5C13 11.3284 12.3284 12 11.5 12H6.5C5.67157 12 5 11.3284 5 10.5V3.5C5 2.67157 5.67157 2 6.5 2H11.5ZM11.5 3H6.5C6.22386 3 6 3.22386 6 3.5V10.5C6 10.7761 6.22386 11 6.5 11H11.5C11.7761 11 12 10.7761 12 10.5V3.5C12 3.22386 11.7761 3 11.5 3Z",fill:a}));const h=({width:r,height:s,fill:a})=>t("svg",{width:r,height:s,viewBox:"0 0 16 16",xmlns:"http://www.w3.org/2000/svg"},t("path",{d:"M8 14C11.3137 14 14 11.3137 14 8C14 4.68629 11.3137 2 8 2C4.68629 2 2 4.68629 2 8C2 11.3137 4.68629 14 8 14ZM8 3C8.37372 3 8.87543 3.35608 9.31258 4.31781C9.4073 4.52619 9.49448 4.75446 9.57265 5H6.42735C6.50552 4.75446 6.5927 4.52619 6.68742 4.31781C7.12457 3.35608 7.62628 3 8 3ZM5.77705 3.90401C5.62614 4.23601 5.49428 4.6038 5.38411 5H3.99963C4.52341 4.30269 5.22525 3.74677 6.03766 3.39978C5.94287 3.56117 5.85596 3.7304 5.77705 3.90401ZM5.16299 6C5.05694 6.6275 5 7.30146 5 8C5 8.69854 5.05694 9.3725 5.16299 10H3.41604C3.14845 9.38754 3 8.7111 3 8C3 7.2889 3.14845 6.61246 3.41604 6H5.16299ZM5.38411 11C5.49428 11.3962 5.62614 11.764 5.77705 12.096C5.85596 12.2696 5.94287 12.4388 6.03766 12.6002C5.22525 12.2532 4.52341 11.6973 3.99963 11H5.38411ZM6.42735 11H9.57265C9.49448 11.2455 9.4073 11.4738 9.31258 11.6822C8.87543 12.6439 8.37372 13 8 13C7.62628 13 7.12457 12.6439 6.68742 11.6822C6.5927 11.4738 6.50552 11.2455 6.42735 11ZM9.82134 10H6.17866C6.06438 9.3892 6 8.71396 6 8C6 7.28604 6.06438 6.6108 6.17866 6H9.82134C9.93562 6.6108 10 7.28604 10 8C10 8.71396 9.93562 9.3892 9.82134 10ZM10.6159 11H12.0004C11.4766 11.6973 10.7747 12.2532 9.96234 12.6002C10.0571 12.4388 10.144 12.2696 10.2229 12.096C10.3739 11.764 10.5057 11.3962 10.6159 11ZM12.584 10H10.837C10.9431 9.3725 11 8.69854 11 8C11 7.30146 10.9431 6.6275 10.837 6H12.584C12.8516 6.61246 13 7.2889 13 8C13 8.7111 12.8516 9.38754 12.584 10ZM9.96234 3.39978C10.7747 3.74677 11.4766 4.30269 12.0004 5H10.6159C10.5057 4.6038 10.3739 4.23601 10.2229 3.90401C10.144 3.7304 10.0571 3.56117 9.96234 3.39978Z",fill:a}));const d=c.get;const f=c.set;const g=(t,r)=>d(t)===r;function b({transcripts:r}){const s=()=>{f("searchTerm","");f("toolbarState","default")};const a=async()=>{const t={"text/plain":r.map((t=>`${t.ts} ${t.speaker}: ${t.text}`)).join("\n")};const s=new ClipboardItem(t);await navigator.clipboard.write([s])};return t("div",{class:"toolbar"},g("toolbarState","default")&&t("div",{class:"controls"},t("button",{onClick:()=>f("toolbarState","search")},t(l,{height:16,fill:"#2C2C2C"}),"Search"),t("button",{onClick:a},t(p,{height:16,fill:"#2C2C2C"}),"Copy"),t("button",{onClick:()=>f("toolbarState","language")},t(h,{height:16,fill:"#2C2C2C"}),"Language")),g("toolbarState","search")&&t("div",{class:"search"},t("input",{type:"text",value:d("searchTerm"),onInput:t=>f("searchTerm",t.target.value),onKeyDown:t=>t.key==="Escape"&&s(),placeholder:"Search transcript",autoFocus:true}),t("button",{class:"clear",onClick:s},"Cancel")),g("toolbarState","language")&&t("div",{class:"language"},t("select",null,t("option",{value:"en"},"English"),t("option",{value:"fr"},"French")),t("button",{class:"regenerate"},"Regenerate"),t("button",{class:"clear",onClick:s},"Done")))}const C=':host{--background:white;--font-family:"Inter", sans-serif;--border-radius:8px}.nylas-transcript{background-color:var(--background);border-radius:var(--border-radius);border:1px solid #e0e6f9;font-size:14px;font-family:var(--font-family);font-optical-sizing:auto}.nylas-transcript .toolbar{padding:20px 20px}.nylas-transcript .toolbar input,.nylas-transcript .toolbar select{border:1px solid #4169e1;padding:10px 20px;border-radius:6px;width:100%}.nylas-transcript .toolbar button.clear{background:none;border:none;cursor:pointer;font-size:14px;font-family:var(--font-family)}.nylas-transcript .toolbar .controls{display:flex;align-items:center;justify-content:stretch;gap:6px}.nylas-transcript .toolbar .controls button{font-family:var(--font-family);cursor:pointer;background-color:white;border:1px solid #c7dbf9;border-radius:8px;padding-top:12px;padding-bottom:12px;flex-grow:1;letter-spacing:-4%;display:flex;align-items:center;justify-content:center}.nylas-transcript .toolbar .controls button svg{margin-right:6px}.nylas-transcript .toolbar .controls button:active{background-color:#f0f4f9}.nylas-transcript .toolbar .search,.nylas-transcript .toolbar .language{display:flex;align-items:center;justify-content:space-between;gap:20px}.nylas-transcript .language button.regenerate{width:93px;border-radius:8px;padding:12px 8px;text-align:center;outline:0;border:none;background-color:#4169e1;color:white}.nylas-transcript .transcripts{max-height:50vh;overflow-y:auto;border-top:1px solid #ebeff6}.nylas-transcript .transcripts .no-results{padding:20px;text-align:center;color:rgba(0, 0, 0, 0.6)}.nylas-transcript .transcripts .transcripts-item{padding:16px 18px;gap:20px;display:flex;line-height:24px;border-bottom:1px solid #ebeff6;transition:0.5s background-color ease-in-out;font-size:14px}.nylas-transcript .transcripts .transcripts-item .highlight{background-color:yellow}.nylas-transcript .transcripts .transcripts-item .copy-btn{fill:#4b4b4b;cursor:pointer;width:24px;transition:0.3s transform ease-in-out}.nylas-transcript .transcripts .transcripts-item .copy-btn:active{fill:#9747ff;transform:scale(2)}.nylas-transcript .transcripts .transcripts-item .speaker{font-weight:500;font-size:16px;margin-bottom:0.5rem}.nylas-transcript .transcripts .transcripts-item.active{background-color:#ebeff6}.nylas-transcript .transcripts .transcripts-item .time{color:#9747ff;font-weight:600;min-width:60px}';const u=C;a.extend(n);const m=({text:r,highlight:s})=>{if(s){r=r.replace(new RegExp(s,"gi"),`<span class="highlight">${s}</span>`)}return t("div",{innerHTML:r})};const y=class{constructor(t){r(this,t);this.focusedIndex=-1;this.autoscroll=true;this.transcript=undefined}componentDidLoad(){c.onChange("style",(t=>{console.log("Style change",t);if(this.el.shadowRoot&&t){this.el.shadowRoot.adoptedStyleSheets=[t]}}))}get transcripts(){const t=e.get("videoTime");const r=c.get("searchTerm");if(!this.transcript)return[];const s=this.transcript.findIndex((r=>r.start/1e3>=t))-1;if(s>=0&&this.autoscroll){this.transcriptContainer.querySelector(".active")?.scrollIntoView({behavior:"smooth",block:"center"})}let a=this.transcript.map(((t,r)=>({...t,active:r===s,ts:t.start?this.secondsToStr(t.start):null})));if(r){a=a.filter((t=>t.text.toLowerCase().includes(r.toLowerCase())))}return a}secondsToStr(t){if(t<36e5){return a.utc(t).format("mm:ss")}else{return a.utc(t).format("HH:mm:ss")}}handleCopy(t){navigator.clipboard.writeText(`${t.ts} ${t.speaker}: ${t.text}`)}render(){return t("div",{key:"690629131ffa02c83db097568bcb9d983934a52d",class:"nylas-transcript"},t(b,{key:"e259b18c6f56c48881b305e87540ccf8752299ad",transcripts:this.transcripts}),t("div",{key:"e9fd658295e29bf38877e3bf30c324710e732b8a",class:"transcripts",ref:t=>this.transcriptContainer=t},!this.transcripts.length&&t("div",{class:"no-results"},"Transcript not available."),this.transcripts.map(((r,s)=>t("div",{class:{"transcripts-item":true,active:r.active},onPointerEnter:()=>this.focusedIndex=s,onPointerLeave:()=>this.focusedIndex=-1},r.ts&&t("div",{class:"time"},this.focusedIndex===s?t("span",{onClick:()=>this.handleCopy(r)},t(p,{className:"copy-btn"})):r.ts),t("div",{class:"message"},t("div",{class:"speaker"},r.speaker),t(m,{text:r.text,highlight:c.get("searchTerm")})))))))}get el(){return s(this)}};y.style=u;export{y as nylas_transcript};
|
|
2
|
+
//# sourceMappingURL=p-f4881c71.entry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["styleSheet","CSSStyleSheet","replaceSync","transcriptStore","createStore","style","toolbarState","searchTerm","SearchIcon","width","height","fill","h","viewBox","xmlns","d","CopyIcon","className","class","LangIcon","get","set","is","a","b","Toolbar","transcripts","handleClearSearch","handleCopy","async","clipboardItemData","map","t","ts","speaker","text","join","clipboardItem","ClipboardItem","navigator","clipboard","write","onClick","type","value","onInput","e","target","onKeyDown","key","placeholder","autoFocus","nylasTranscriptCss","NylasTranscriptStyle0","dayjs","extend","utc","Text","highlight","replace","RegExp","innerHTML","NylasTranscript","componentDidLoad","onChange","val","console","log","this","el","shadowRoot","adoptedStyleSheets","time","store","transcript","candidateIndex","findIndex","item","start","autoscroll","transcriptContainer","querySelector","scrollIntoView","behavior","block","res","index","active","secondsToStr","filter","x","toLowerCase","includes","milliseconds","format","writeText","render","ref","length","idx","onPointerEnter","focusedIndex","onPointerLeave"],"sources":["src/components/nylas-notebook/store/transcript-store.ts","src/components/nylas-notebook/icons.tsx","src/components/nylas-notebook/nylas-transcript/transcript-toolbar.tsx","src/components/nylas-notebook/nylas-transcript/nylas-transcript.scss?tag=nylas-transcript&encapsulation=shadow","src/components/nylas-notebook/nylas-transcript/nylas-transcript.tsx"],"sourcesContent":["import { createStore } from '@stencil/store';\n\nconst styleSheet = new CSSStyleSheet();\nstyleSheet.replaceSync(`\n :host {\n font-family: Arial, sans-serif;\n }\n`);\n\n// Map each key to its respective type\nexport interface TranscriptStore {\n toolbarState: 'default' | 'search' | 'language';\n style?: CSSStyleSheet;\n searchTerm: string;\n}\n\n// nylas-video-player store\nexport const transcriptStore = createStore<TranscriptStore>({\n style: styleSheet,\n toolbarState: 'default',\n searchTerm: '',\n});\n","import { FunctionalComponent, h } from '@stencil/core';\n\ninterface IconProps {\n width?: string | number;\n height?: string | number;\n className?: string;\n fill?: string;\n stroke?: string;\n}\n\nexport const SearchIcon: FunctionalComponent<IconProps> = ({ width, height, fill }) => (\n <svg viewBox=\"0 0 16 16\" width={width} height={height} xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M9.30887 10.016C8.53903 10.6318 7.56252 11 6.5 11C4.01472 11 2 8.98531 2 6.50002C2 4.01473 4.01472 2 6.5 2C8.98528 2 11 4.01473 11 6.50002C11 7.56252 10.6318 8.53901 10.016 9.30885L13.8536 13.1464C14.0488 13.3417 14.0488 13.6583 13.8536 13.8536C13.6583 14.0488 13.3417 14.0488 13.1464 13.8536L9.30887 10.016ZM10 6.50002C10 4.56701 8.433 3 6.5 3C4.567 3 3 4.56701 3 6.50002C3 8.43302 4.567 10 6.5 10C8.433 10 10 8.43302 10 6.50002Z\"\n fill={fill}\n />\n </svg>\n);\n\nexport const CopyIcon: FunctionalComponent<IconProps> = ({ width, height, fill, className }) => (\n <svg width={width} height={height} class={className} viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M4.00029 4.08525L4 10.5C4 11.8255 5.03154 12.91 6.33562 12.9947L6.5 13L10.9144 13.0007C10.7083 13.5829 10.1528 14 9.5 14H6C4.34315 14 3 12.6569 3 11V5.5C3 4.84678 3.41754 4.29109 4.00029 4.08525ZM11.5 2C12.3284 2 13 2.67157 13 3.5V10.5C13 11.3284 12.3284 12 11.5 12H6.5C5.67157 12 5 11.3284 5 10.5V3.5C5 2.67157 5.67157 2 6.5 2H11.5ZM11.5 3H6.5C6.22386 3 6 3.22386 6 3.5V10.5C6 10.7761 6.22386 11 6.5 11H11.5C11.7761 11 12 10.7761 12 10.5V3.5C12 3.22386 11.7761 3 11.5 3Z\"\n fill={fill}\n />\n </svg>\n);\nexport const LangIcon: FunctionalComponent<IconProps> = ({ width, height, fill }) => (\n <svg width={width} height={height} viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M8 14C11.3137 14 14 11.3137 14 8C14 4.68629 11.3137 2 8 2C4.68629 2 2 4.68629 2 8C2 11.3137 4.68629 14 8 14ZM8 3C8.37372 3 8.87543 3.35608 9.31258 4.31781C9.4073 4.52619 9.49448 4.75446 9.57265 5H6.42735C6.50552 4.75446 6.5927 4.52619 6.68742 4.31781C7.12457 3.35608 7.62628 3 8 3ZM5.77705 3.90401C5.62614 4.23601 5.49428 4.6038 5.38411 5H3.99963C4.52341 4.30269 5.22525 3.74677 6.03766 3.39978C5.94287 3.56117 5.85596 3.7304 5.77705 3.90401ZM5.16299 6C5.05694 6.6275 5 7.30146 5 8C5 8.69854 5.05694 9.3725 5.16299 10H3.41604C3.14845 9.38754 3 8.7111 3 8C3 7.2889 3.14845 6.61246 3.41604 6H5.16299ZM5.38411 11C5.49428 11.3962 5.62614 11.764 5.77705 12.096C5.85596 12.2696 5.94287 12.4388 6.03766 12.6002C5.22525 12.2532 4.52341 11.6973 3.99963 11H5.38411ZM6.42735 11H9.57265C9.49448 11.2455 9.4073 11.4738 9.31258 11.6822C8.87543 12.6439 8.37372 13 8 13C7.62628 13 7.12457 12.6439 6.68742 11.6822C6.5927 11.4738 6.50552 11.2455 6.42735 11ZM9.82134 10H6.17866C6.06438 9.3892 6 8.71396 6 8C6 7.28604 6.06438 6.6108 6.17866 6H9.82134C9.93562 6.6108 10 7.28604 10 8C10 8.71396 9.93562 9.3892 9.82134 10ZM10.6159 11H12.0004C11.4766 11.6973 10.7747 12.2532 9.96234 12.6002C10.0571 12.4388 10.144 12.2696 10.2229 12.096C10.3739 11.764 10.5057 11.3962 10.6159 11ZM12.584 10H10.837C10.9431 9.3725 11 8.69854 11 8C11 7.30146 10.9431 6.6275 10.837 6H12.584C12.8516 6.61246 13 7.2889 13 8C13 8.7111 12.8516 9.38754 12.584 10ZM9.96234 3.39978C10.7747 3.74677 11.4766 4.30269 12.0004 5H10.6159C10.5057 4.6038 10.3739 4.23601 10.2229 3.90401C10.144 3.7304 10.0571 3.56117 9.96234 3.39978Z\"\n fill={fill}\n />\n </svg>\n);\n\nexport const EditIcon: FunctionalComponent<IconProps> = ({ width, height, fill }) => (\n <svg width={width} height={height} viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M13.6569 2.3436C14.4379 3.12465 14.4379 4.39098 13.6569 5.17203L6.27044 12.5585C5.95004 12.8789 5.54859 13.1062 5.10901 13.2161L2.81801 13.7888C2.45182 13.8804 2.12013 13.5487 2.21167 13.1825L2.78442 10.8915C2.89432 10.4519 3.12161 10.0505 3.44201 9.73006L10.8285 2.3436C11.6095 1.56255 12.8759 1.56255 13.6569 2.3436ZM10.1213 4.46481L4.14912 10.4372C3.95688 10.6294 3.8205 10.8703 3.75457 11.134L3.38393 12.6166L4.86648 12.2459C5.13022 12.18 5.37109 12.0436 5.56333 11.8514L11.5353 5.87881L10.1213 4.46481ZM11.5356 3.05071L10.8283 3.75781L12.2423 5.17181L12.9498 4.46492C13.3403 4.07439 13.3403 3.44123 12.9498 3.05071C12.5593 2.66018 11.9261 2.66018 11.5356 3.05071Z\"\n fill={fill}\n />\n </svg>\n);\n","import { h } from '@stencil/core';\nimport { transcriptStore, TranscriptStore } from './../store/transcript-store';\nimport { SearchIcon, CopyIcon, LangIcon } from '../icons';\n\nconst get = transcriptStore.get;\nconst set = transcriptStore.set;\nconst is = <K extends keyof TranscriptStore>(a: K, b: TranscriptStore[K]) => get(a) === b;\n\nexport default function Toolbar({ transcripts }) {\n const handleClearSearch = () => {\n set('searchTerm', '');\n set('toolbarState', 'default');\n };\n\n const handleCopy = async () => {\n const clipboardItemData = {\n 'text/plain': transcripts.map(t => `${t.ts} ${t.speaker}: ${t.text}`).join('\\n'),\n };\n const clipboardItem = new ClipboardItem(clipboardItemData);\n await navigator.clipboard.write([clipboardItem]);\n };\n\n return (\n <div class=\"toolbar\">\n {/* Default State */}\n {is('toolbarState', 'default') && (\n <div class=\"controls\">\n <button onClick={() => set('toolbarState', 'search')}>\n <SearchIcon height={16} fill=\"#2C2C2C\" />\n Search\n </button>\n\n <button onClick={handleCopy}>\n <CopyIcon height={16} fill=\"#2C2C2C\" />\n Copy\n </button>\n\n <button onClick={() => set('toolbarState', 'language')}>\n <LangIcon height={16} fill=\"#2C2C2C\" />\n Language\n </button>\n </div>\n )}\n {/* Search */}\n {is('toolbarState', 'search') && (\n <div class=\"search\">\n <input\n type=\"text\"\n value={get('searchTerm')}\n onInput={e => set('searchTerm', (e.target as HTMLInputElement).value)}\n onKeyDown={e => e.key === 'Escape' && handleClearSearch()}\n placeholder=\"Search transcript\"\n autoFocus\n />\n <button class=\"clear\" onClick={handleClearSearch}>\n Cancel\n </button>\n </div>\n )}\n {/* Language */}\n {is('toolbarState', 'language') && (\n <div class=\"language\">\n <select>\n <option value=\"en\">English</option>\n <option value=\"fr\">French</option>\n </select>\n <button class=\"regenerate\">Regenerate</button>\n <button class=\"clear\" onClick={handleClearSearch}>\n Done\n </button>\n </div>\n )}\n </div>\n );\n}\n",":host {\n --background: white;\n --font-family: 'Inter', sans-serif;\n --border-radius: 8px;\n}\n\n.nylas-transcript {\n background-color: var(--background);\n border-radius: var(--border-radius);\n border: 1px solid #e0e6f9;\n font-size: 14px;\n font-family: var(--font-family);\n font-optical-sizing: auto;\n\n .toolbar {\n padding: 20px 20px;\n\n input,\n select {\n border: 1px solid #4169e1;\n padding: 10px 20px;\n border-radius: 6px;\n width: 100%;\n }\n\n button.clear {\n background: none;\n border: none;\n cursor: pointer;\n font-size: 14px;\n font-family: var(--font-family);\n }\n\n .controls {\n display: flex;\n align-items: center;\n justify-content: stretch;\n gap: 6px;\n\n button {\n font-family: var(--font-family);\n cursor: pointer;\n background-color: white;\n border: 1px solid #c7dbf9;\n border-radius: 8px;\n padding-top: 12px;\n padding-bottom: 12px;\n flex-grow: 1;\n letter-spacing: -4%;\n display: flex;\n align-items: center;\n justify-content: center;\n\n svg {\n margin-right: 6px;\n }\n\n &:active {\n background-color: #f0f4f9;\n }\n }\n }\n\n .search,\n .language {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 20px;\n }\n }\n\n .language {\n button.regenerate {\n width: 93px;\n border-radius: 8px;\n padding: 12px 8px;\n text-align: center;\n outline: 0;\n border: none;\n background-color: #4169e1;\n color: white;\n }\n }\n\n .transcripts {\n max-height: 50vh;\n overflow-y: auto;\n border-top: 1px solid #ebeff6;\n\n .no-results {\n padding: 20px;\n text-align: center;\n color: rgba(0, 0, 0, 0.6);\n }\n\n .transcripts-item {\n padding: 16px 18px;\n gap: 20px;\n display: flex;\n line-height: 24px;\n border-bottom: 1px solid #ebeff6;\n transition: 0.5s background-color ease-in-out;\n font-size: 14px;\n\n .highlight {\n background-color: yellow;\n }\n\n .copy-btn {\n fill: #4b4b4b;\n cursor: pointer;\n width: 24px;\n transition: 0.3s transform ease-in-out;\n\n &:active {\n fill: #9747ff;\n transform: scale(2);\n }\n }\n\n .speaker {\n font-weight: 500;\n font-size: 16px;\n margin-bottom: 0.5rem;\n }\n\n &.active {\n background-color: #ebeff6;\n }\n\n .time {\n color: #9747ff;\n font-weight: 600;\n min-width: 60px;\n }\n }\n }\n}\n","import { Component, h, Element, Prop, State } from '@stencil/core';\nimport dayjs from 'dayjs';\nimport utc from 'dayjs/plugin/utc';\nimport { videoStore as store } from '../store/notebook-store';\nimport Toolbar from './transcript-toolbar';\nimport { transcriptStore } from '../store/transcript-store';\nimport { CopyIcon } from '../icons';\n\ndayjs.extend(utc); // needed as utc is a separate plugin\n\nconst Text = ({ text, highlight }) => {\n if (highlight) {\n text = text.replace(new RegExp(highlight, 'gi'), `<span class=\"highlight\">${highlight}</span>`);\n }\n return <div innerHTML={text}></div>;\n};\n\n@Component({\n tag: 'nylas-transcript',\n styleUrl: 'nylas-transcript.scss',\n shadow: true,\n})\nexport class NylasTranscript {\n @Element() el!: HTMLElement;\n transcriptContainer!: HTMLDivElement;\n @State() focusedIndex: number = -1;\n\n @Prop() autoscroll: boolean = true;\n @Prop() transcript!: any;\n\n componentDidLoad() {\n transcriptStore.onChange('style', val => {\n console.log('Style change', val);\n if (this.el.shadowRoot && val) {\n this.el.shadowRoot.adoptedStyleSheets = [val];\n }\n });\n }\n\n get transcripts() {\n const time = store.get('videoTime');\n const searchTerm = transcriptStore.get('searchTerm');\n if (!this.transcript) return [];\n const candidateIndex = this.transcript.findIndex(item => item.start / 1000 >= time) - 1;\n // Scroll to proper video time\n if (candidateIndex >= 0 && this.autoscroll) {\n this.transcriptContainer.querySelector('.active')?.scrollIntoView({ behavior: 'smooth', block: 'center' });\n }\n // TODO: map different providers\n let res = this.transcript.map((item, index) => ({\n ...item,\n active: index === candidateIndex,\n ts: item.start ? this.secondsToStr(item.start) : null,\n }));\n if (searchTerm) {\n res = res.filter(x => x.text.toLowerCase().includes(searchTerm.toLowerCase()));\n }\n return res;\n }\n\n secondsToStr(milliseconds: number) {\n if (milliseconds < 3600000) {\n return dayjs.utc(milliseconds).format('mm:ss');\n } else {\n return dayjs.utc(milliseconds).format('HH:mm:ss');\n }\n }\n\n private handleCopy(item) {\n navigator.clipboard.writeText(`${item.ts} ${item.speaker}: ${item.text}`);\n }\n\n render() {\n return (\n <div class=\"nylas-transcript\">\n {/* <Tabs /> */}\n <Toolbar transcripts={this.transcripts} />\n <div class=\"transcripts\" ref={el => (this.transcriptContainer = el as HTMLDivElement)}>\n {!this.transcripts.length && <div class=\"no-results\">Transcript not available.</div>}\n {this.transcripts.map((item, idx) => {\n return (\n <div\n class={{\n 'transcripts-item': true,\n 'active': item.active,\n }}\n onPointerEnter={() => (this.focusedIndex = idx)}\n onPointerLeave={() => (this.focusedIndex = -1)}\n >\n {item.ts && (\n <div class=\"time\">\n {this.focusedIndex === idx ? (\n <span onClick={() => this.handleCopy(item)}>\n <CopyIcon className=\"copy-btn\" />\n </span>\n ) : (\n item.ts\n )}\n </div>\n )}\n {/* Message Part */}\n <div class=\"message\">\n <div class=\"speaker\">{item.speaker}</div>\n <Text text={item.text} highlight={transcriptStore.get('searchTerm')} />\n </div>\n </div>\n );\n })}\n </div>\n </div>\n );\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nylas/web-elements",
|
|
3
|
-
"version": "0.0.0-test-
|
|
3
|
+
"version": "0.0.0-test-20250327161320",
|
|
4
4
|
"description": "Nylas Web Elements",
|
|
5
5
|
"main": "dist/index.cjs.js",
|
|
6
6
|
"module": "dist/index.js",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
"rrule": "2.8.1",
|
|
42
42
|
"sanitize-html": "^2.13.0",
|
|
43
43
|
"sortablejs": "^1.15.6",
|
|
44
|
-
"@nylas/core": "^0.0.0-test-
|
|
44
|
+
"@nylas/core": "^0.0.0-test-20250327161320",
|
|
45
45
|
"@nylas/identity": "^3.0.0"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"start": "stencil build --prod --watch --serve --port 3333",
|
|
82
82
|
"start:dev": "stencil build --watch --serve --port 3333",
|
|
83
83
|
"local:dev": "stencil build --dev --watch --serve --config stencil.dev.config.ts --port 3333",
|
|
84
|
-
"test": "stencil test --spec && playwright test",
|
|
84
|
+
"test": "if [ -n \"$IS_CI\" ]; then pnpm exec playwright install; fi && stencil test --spec && playwright test",
|
|
85
85
|
"test.playwright": "playwright test",
|
|
86
86
|
"unit.test": "stencil test --spec",
|
|
87
87
|
"test.watch": "stencil test --spec --e2e --watchAll",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"names":["styleSheet","CSSStyleSheet","replaceSync","transcriptStore","createStore","style","toolbarState","searchTerm","SearchIcon","width","height","fill","h","viewBox","xmlns","d","CopyIcon","className","class","LangIcon","get","set","is","a","b","Toolbar","transcripts","handleClearSearch","handleCopy","async","clipboardItemData","map","t","ts","speaker","text","join","clipboardItem","ClipboardItem","navigator","clipboard","write","onClick","type","value","onInput","e","target","onKeyDown","key","placeholder","autoFocus","nylasTranscriptCss","NylasTranscriptStyle0","dayjs","extend","utc","Text","highlight","replace","RegExp","innerHTML","NylasTranscript","componentDidLoad","onChange","val","console","log","this","el","shadowRoot","adoptedStyleSheets","time","store","transcript","candidateIndex","findIndex","item","start","autoscroll","transcriptContainer","querySelector","scrollIntoView","behavior","block","res","index","active","secondsToStr","filter","x","toLowerCase","includes","milliseconds","format","writeText","render","ref","idx","onPointerEnter","focusedIndex","onPointerLeave"],"sources":["src/components/nylas-notebook/store/transcript-store.ts","src/components/nylas-notebook/icons.tsx","src/components/nylas-notebook/nylas-transcript/transcript-toolbar.tsx","src/components/nylas-notebook/nylas-transcript/nylas-transcript.scss?tag=nylas-transcript&encapsulation=shadow","src/components/nylas-notebook/nylas-transcript/nylas-transcript.tsx"],"sourcesContent":["import { createStore } from '@stencil/store';\n\nconst styleSheet = new CSSStyleSheet();\nstyleSheet.replaceSync(`\n :host {\n font-family: Arial, sans-serif;\n }\n`);\n\n// Map each key to its respective type\nexport interface TranscriptStore {\n toolbarState: 'default' | 'search' | 'language';\n style?: CSSStyleSheet;\n searchTerm: string;\n}\n\n// nylas-video-player store\nexport const transcriptStore = createStore<TranscriptStore>({\n style: styleSheet,\n toolbarState: 'default',\n searchTerm: '',\n});\n","import { FunctionalComponent, h } from '@stencil/core';\n\ninterface IconProps {\n width?: string | number;\n height?: string | number;\n className?: string;\n fill?: string;\n stroke?: string;\n}\n\nexport const SearchIcon: FunctionalComponent<IconProps> = ({ width, height, fill }) => (\n <svg viewBox=\"0 0 16 16\" width={width} height={height} xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M9.30887 10.016C8.53903 10.6318 7.56252 11 6.5 11C4.01472 11 2 8.98531 2 6.50002C2 4.01473 4.01472 2 6.5 2C8.98528 2 11 4.01473 11 6.50002C11 7.56252 10.6318 8.53901 10.016 9.30885L13.8536 13.1464C14.0488 13.3417 14.0488 13.6583 13.8536 13.8536C13.6583 14.0488 13.3417 14.0488 13.1464 13.8536L9.30887 10.016ZM10 6.50002C10 4.56701 8.433 3 6.5 3C4.567 3 3 4.56701 3 6.50002C3 8.43302 4.567 10 6.5 10C8.433 10 10 8.43302 10 6.50002Z\"\n fill={fill}\n />\n </svg>\n);\n\nexport const CopyIcon: FunctionalComponent<IconProps> = ({ width, height, fill, className }) => (\n <svg width={width} height={height} class={className} viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M4.00029 4.08525L4 10.5C4 11.8255 5.03154 12.91 6.33562 12.9947L6.5 13L10.9144 13.0007C10.7083 13.5829 10.1528 14 9.5 14H6C4.34315 14 3 12.6569 3 11V5.5C3 4.84678 3.41754 4.29109 4.00029 4.08525ZM11.5 2C12.3284 2 13 2.67157 13 3.5V10.5C13 11.3284 12.3284 12 11.5 12H6.5C5.67157 12 5 11.3284 5 10.5V3.5C5 2.67157 5.67157 2 6.5 2H11.5ZM11.5 3H6.5C6.22386 3 6 3.22386 6 3.5V10.5C6 10.7761 6.22386 11 6.5 11H11.5C11.7761 11 12 10.7761 12 10.5V3.5C12 3.22386 11.7761 3 11.5 3Z\"\n fill={fill}\n />\n </svg>\n);\nexport const LangIcon: FunctionalComponent<IconProps> = ({ width, height, fill }) => (\n <svg width={width} height={height} viewBox=\"0 0 16 16\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M8 14C11.3137 14 14 11.3137 14 8C14 4.68629 11.3137 2 8 2C4.68629 2 2 4.68629 2 8C2 11.3137 4.68629 14 8 14ZM8 3C8.37372 3 8.87543 3.35608 9.31258 4.31781C9.4073 4.52619 9.49448 4.75446 9.57265 5H6.42735C6.50552 4.75446 6.5927 4.52619 6.68742 4.31781C7.12457 3.35608 7.62628 3 8 3ZM5.77705 3.90401C5.62614 4.23601 5.49428 4.6038 5.38411 5H3.99963C4.52341 4.30269 5.22525 3.74677 6.03766 3.39978C5.94287 3.56117 5.85596 3.7304 5.77705 3.90401ZM5.16299 6C5.05694 6.6275 5 7.30146 5 8C5 8.69854 5.05694 9.3725 5.16299 10H3.41604C3.14845 9.38754 3 8.7111 3 8C3 7.2889 3.14845 6.61246 3.41604 6H5.16299ZM5.38411 11C5.49428 11.3962 5.62614 11.764 5.77705 12.096C5.85596 12.2696 5.94287 12.4388 6.03766 12.6002C5.22525 12.2532 4.52341 11.6973 3.99963 11H5.38411ZM6.42735 11H9.57265C9.49448 11.2455 9.4073 11.4738 9.31258 11.6822C8.87543 12.6439 8.37372 13 8 13C7.62628 13 7.12457 12.6439 6.68742 11.6822C6.5927 11.4738 6.50552 11.2455 6.42735 11ZM9.82134 10H6.17866C6.06438 9.3892 6 8.71396 6 8C6 7.28604 6.06438 6.6108 6.17866 6H9.82134C9.93562 6.6108 10 7.28604 10 8C10 8.71396 9.93562 9.3892 9.82134 10ZM10.6159 11H12.0004C11.4766 11.6973 10.7747 12.2532 9.96234 12.6002C10.0571 12.4388 10.144 12.2696 10.2229 12.096C10.3739 11.764 10.5057 11.3962 10.6159 11ZM12.584 10H10.837C10.9431 9.3725 11 8.69854 11 8C11 7.30146 10.9431 6.6275 10.837 6H12.584C12.8516 6.61246 13 7.2889 13 8C13 8.7111 12.8516 9.38754 12.584 10ZM9.96234 3.39978C10.7747 3.74677 11.4766 4.30269 12.0004 5H10.6159C10.5057 4.6038 10.3739 4.23601 10.2229 3.90401C10.144 3.7304 10.0571 3.56117 9.96234 3.39978Z\"\n fill={fill}\n />\n </svg>\n);\n\nexport const EditIcon: FunctionalComponent<IconProps> = ({ width, height, fill }) => (\n <svg width={width} height={height} viewBox=\"0 0 16 16\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path\n d=\"M13.6569 2.3436C14.4379 3.12465 14.4379 4.39098 13.6569 5.17203L6.27044 12.5585C5.95004 12.8789 5.54859 13.1062 5.10901 13.2161L2.81801 13.7888C2.45182 13.8804 2.12013 13.5487 2.21167 13.1825L2.78442 10.8915C2.89432 10.4519 3.12161 10.0505 3.44201 9.73006L10.8285 2.3436C11.6095 1.56255 12.8759 1.56255 13.6569 2.3436ZM10.1213 4.46481L4.14912 10.4372C3.95688 10.6294 3.8205 10.8703 3.75457 11.134L3.38393 12.6166L4.86648 12.2459C5.13022 12.18 5.37109 12.0436 5.56333 11.8514L11.5353 5.87881L10.1213 4.46481ZM11.5356 3.05071L10.8283 3.75781L12.2423 5.17181L12.9498 4.46492C13.3403 4.07439 13.3403 3.44123 12.9498 3.05071C12.5593 2.66018 11.9261 2.66018 11.5356 3.05071Z\"\n fill={fill}\n />\n </svg>\n);\n","import { h } from '@stencil/core';\nimport { transcriptStore, TranscriptStore } from './../store/transcript-store';\nimport { SearchIcon, CopyIcon, LangIcon } from '../icons';\n\nconst get = transcriptStore.get;\nconst set = transcriptStore.set;\nconst is = <K extends keyof TranscriptStore>(a: K, b: TranscriptStore[K]) => get(a) === b;\n\nexport default function Toolbar({ transcripts }) {\n const handleClearSearch = () => {\n set('searchTerm', '');\n set('toolbarState', 'default');\n };\n\n const handleCopy = async () => {\n const clipboardItemData = {\n 'text/plain': transcripts.map(t => `${t.ts} ${t.speaker}: ${t.text}`).join('\\n'),\n };\n const clipboardItem = new ClipboardItem(clipboardItemData);\n await navigator.clipboard.write([clipboardItem]);\n };\n\n return (\n <div class=\"toolbar\">\n {/* Default State */}\n {is('toolbarState', 'default') && (\n <div class=\"controls\">\n <button onClick={() => set('toolbarState', 'search')}>\n <SearchIcon height={16} fill=\"#2C2C2C\" />\n Search\n </button>\n\n <button onClick={handleCopy}>\n <CopyIcon height={16} fill=\"#2C2C2C\" />\n Copy\n </button>\n\n <button onClick={() => set('toolbarState', 'language')}>\n <LangIcon height={16} fill=\"#2C2C2C\" />\n Language\n </button>\n </div>\n )}\n {/* Search */}\n {is('toolbarState', 'search') && (\n <div class=\"search\">\n <input\n type=\"text\"\n value={get('searchTerm')}\n onInput={e => set('searchTerm', (e.target as HTMLInputElement).value)}\n onKeyDown={e => e.key === 'Escape' && handleClearSearch()}\n placeholder=\"Search transcript\"\n autoFocus\n />\n <button class=\"clear\" onClick={handleClearSearch}>\n Cancel\n </button>\n </div>\n )}\n {/* Language */}\n {is('toolbarState', 'language') && (\n <div class=\"language\">\n <select>\n <option value=\"en\">English</option>\n <option value=\"fr\">French</option>\n </select>\n <button class=\"regenerate\">Regenerate</button>\n <button class=\"clear\" onClick={handleClearSearch}>\n Done\n </button>\n </div>\n )}\n </div>\n );\n}\n",":host {\n --background: white;\n --font-family: 'Inter', sans-serif;\n --border-radius: 8px;\n}\n\n.nylas-transcript {\n background-color: var(--background);\n border-radius: var(--border-radius);\n border: 1px solid #e0e6f9;\n font-size: 14px;\n font-family: var(--font-family);\n font-optical-sizing: auto;\n\n .toolbar {\n padding: 20px 20px;\n\n input,\n select {\n border: 1px solid #4169e1;\n padding: 10px 20px;\n border-radius: 6px;\n width: 100%;\n }\n\n button.clear {\n background: none;\n border: none;\n cursor: pointer;\n font-size: 14px;\n font-family: var(--font-family);\n }\n\n .controls {\n display: flex;\n align-items: center;\n justify-content: stretch;\n gap: 6px;\n\n button {\n font-family: var(--font-family);\n cursor: pointer;\n background-color: white;\n border: 1px solid #c7dbf9;\n border-radius: 8px;\n padding-top: 12px;\n padding-bottom: 12px;\n flex-grow: 1;\n letter-spacing: -4%;\n display: flex;\n align-items: center;\n justify-content: center;\n\n svg {\n margin-right: 6px;\n }\n\n &:active {\n background-color: #f0f4f9;\n }\n }\n }\n\n .search,\n .language {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 20px;\n }\n }\n\n .language {\n button.regenerate {\n width: 93px;\n border-radius: 8px;\n padding: 12px 8px;\n text-align: center;\n outline: 0;\n border: none;\n background-color: #4169e1;\n color: white;\n }\n }\n\n .transcripts {\n max-height: 50vh;\n overflow-y: auto;\n border-top: 1px solid #ebeff6;\n\n .transcripts-item {\n padding: 16px 18px;\n gap: 20px;\n display: flex;\n line-height: 24px;\n border-bottom: 1px solid #ebeff6;\n transition: 0.5s background-color ease-in-out;\n font-size: 14px;\n\n .highlight {\n background-color: yellow;\n }\n\n .copy-btn {\n fill: #4b4b4b;\n cursor: pointer;\n width: 24px;\n transition: 0.3s transform ease-in-out;\n\n &:active {\n fill: #9747ff;\n transform: scale(2);\n }\n }\n\n .speaker {\n font-weight: 500;\n font-size: 16px;\n margin-bottom: 0.5rem;\n }\n\n &.active {\n background-color: #ebeff6;\n }\n\n .time {\n color: #9747ff;\n font-weight: 600;\n min-width: 60px;\n }\n }\n }\n}\n","import { Component, h, Element, Prop, State } from '@stencil/core';\nimport dayjs from 'dayjs';\nimport utc from 'dayjs/plugin/utc';\nimport { videoStore as store } from '../store/notebook-store';\nimport Toolbar from './transcript-toolbar';\nimport { transcriptStore } from '../store/transcript-store';\nimport { CopyIcon } from '../icons';\n\ndayjs.extend(utc); // needed as utc is a separate plugin\n\nconst Text = ({ text, highlight }) => {\n if (highlight) {\n text = text.replace(new RegExp(highlight, 'gi'), `<span class=\"highlight\">${highlight}</span>`);\n }\n return <div innerHTML={text}></div>;\n};\n\n@Component({\n tag: 'nylas-transcript',\n styleUrl: 'nylas-transcript.scss',\n shadow: true,\n})\nexport class NylasTranscript {\n @Element() el!: HTMLElement;\n transcriptContainer!: HTMLDivElement;\n @State() focusedIndex: number = -1;\n\n @Prop() autoscroll: boolean = true;\n @Prop() transcript!: any;\n\n componentDidLoad() {\n transcriptStore.onChange('style', val => {\n console.log('Style change', val);\n if (this.el.shadowRoot && val) {\n this.el.shadowRoot.adoptedStyleSheets = [val];\n }\n });\n }\n\n get transcripts() {\n const time = store.get('videoTime');\n const searchTerm = transcriptStore.get('searchTerm');\n if (!this.transcript) return [];\n const candidateIndex = this.transcript.findIndex(item => item.start / 1000 >= time) - 1;\n // Scroll to proper video time\n if (candidateIndex >= 0 && this.autoscroll) {\n this.transcriptContainer.querySelector('.active')?.scrollIntoView({ behavior: 'smooth', block: 'center' });\n }\n // TODO: map different providers\n let res = this.transcript.map((item, index) => ({\n ...item,\n active: index === candidateIndex,\n ts: this.secondsToStr(item.start),\n }));\n if (searchTerm) {\n res = res.filter(x => x.text.toLowerCase().includes(searchTerm.toLowerCase()));\n }\n return res;\n }\n\n secondsToStr(milliseconds: number) {\n if (milliseconds < 3600000) {\n return dayjs.utc(milliseconds).format('mm:ss');\n } else {\n return dayjs.utc(milliseconds).format('HH:mm:ss');\n }\n }\n\n private handleCopy(item) {\n navigator.clipboard.writeText(`${item.ts} ${item.speaker}: ${item.text}`);\n }\n\n render() {\n return (\n <div class=\"nylas-transcript\">\n {/* <Tabs /> */}\n <Toolbar transcripts={this.transcripts} />\n <div class=\"transcripts\" ref={el => (this.transcriptContainer = el as HTMLDivElement)}>\n {this.transcripts.map((item, idx) => {\n return (\n <div\n class={{\n 'transcripts-item': true,\n 'active': item.active,\n }}\n onPointerEnter={() => (this.focusedIndex = idx)}\n onPointerLeave={() => (this.focusedIndex = -1)}\n >\n <div class=\"time\">\n {this.focusedIndex === idx ? (\n <span onClick={() => this.handleCopy(item)}>\n <CopyIcon className=\"copy-btn\" />\n </span>\n ) : (\n item.ts\n )}\n </div>\n {/* Message Part */}\n <div class=\"message\">\n <div class=\"speaker\">{item.speaker}</div>\n <Text text={item.text} highlight={transcriptStore.get('searchTerm')} />\n </div>\n </div>\n );\n })}\n </div>\n </div>\n );\n }\n}\n"],"mappings":"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"}
|
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{r as e,h as o,a as t}from"./p-6f5a3998.js";import{v as r}from"./p-890d7f01.js";import"./p-fc5bc07b.js";const i='.video-container{display:flex;flex-direction:column;align-items:center;justify-content:center;background-color:#000;position:relative;box-sizing:border-box;border-radius:8px;font-family:"Inter", serif;font-optical-sizing:auto}.video-container video{width:100%;border-radius:8px}.video-container .play-icon svg{fill:red}.video-container .controls-overlay{color:white;background:linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.8));position:absolute;bottom:0;left:0;right:0;padding:30px 20px;padding-bottom:10px;opacity:1;transition:opacity 0.3s;border-bottom-right-radius:8px;border-bottom-left-radius:8px;display:none;}.video-container .controls-overlay .seek{width:100%}.video-container .controls-overlay input[type=range]{-webkit-appearance:none;appearance:none;background:transparent;cursor:pointer}.video-container .controls-overlay .info{padding-bottom:20px}.video-container .controls-overlay .info .title{font-size:20px}.video-container .controls-overlay .info .description{color:#bbbbbb;font-weight:400;font-size:14px}.video-container .controls-overlay .progress-bar{background-color:rgba(255, 255, 255, 0.5);height:2px;margin:10px 0;transition:width 0.1s}.video-container .controls-overlay .progress-bar .progress{background:white;height:2px}.video-container .controls-overlay .controls{display:flex;align-items:center;justify-content:space-between}.video-container .controls-overlay .controls button{background:none;border:none}.video-container .controls-overlay input[type=range]{-webkit-appearance:none;appearance:none;background:transparent;cursor:pointer;width:15rem}.video-container .controls-overlay input[type=range]:focus{outline:none}.video-container .controls-overlay input[type=range]::-webkit-slider-runnable-track{background-color:#053a5f;border-radius:0.5rem;height:0.5rem}.video-container .controls-overlay input[type=range]::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;margin-top:-12px;background-color:#5cd5eb;height:2rem;width:1rem}.video-container .controls-overlay input[type=range]:focus::-webkit-slider-thumb{border:1px solid #053a5f;outline:3px solid #053a5f;outline-offset:0.125rem}.video-container .controls-overlay input[type=range]::-moz-range-track{background-color:#053a5f;border-radius:0.5rem;height:0.5rem}.video-container .controls-overlay input[type=range]::-moz-range-thumb{border:none;border-radius:0;background-color:#5cd5eb;height:2rem;width:1rem}.video-container .controls-overlay input[type=range]:focus::-moz-range-thumb{border:1px solid #053a5f;outline:3px solid #053a5f;outline-offset:0.125rem}';const n=i;const a=class{constructor(o){e(this,o);this.handleTimeUpdate=()=>{const e=this.videoElement;r.set("videoTime",this.videoElement.currentTime);if(!this.isSeeking){this.seekElement.value=(e.currentTime/e.duration*100).toString()}};this.handlePlay=()=>{this.isPlaying=true;this.videoElement.play()};this.handlePause=()=>{this.isPlaying=false;this.videoElement.pause()};this.videoUrl=undefined;this.isSeeking=false;this.isPlaying=false}inputSeek(e){if(!this.isSeeking)this.isSeeking=true}handleSeek(e){this.isSeeking=false;if(!this.videoElement)return;const o=e.target;this.videoElement.currentTime=parseFloat(o.value)/100*this.videoElement.duration;this.videoElement.play()}get progressPercent(){if(!this.videoElement)return 0;const e=r.get("videoTime");return e/this.videoElement.duration*100}render(){return o("div",{key:"98a898e225274dac6fda72126de7eb3fbe3b73b0",class:"video-container"},o("video",{key:"2938eddacc3020461e2ce61e1d35bc58fd791975",ref:e=>this.videoElement=e,onPlay:this.handlePlay,onPause:this.handlePause,onTimeUpdate:this.handleTimeUpdate,muted:true,controls:true},this.videoUrl&&o("source",{src:this.videoUrl,type:"video/mp4"})),o("div",{key:"d4846bb9f5e06341238a073d54453b546def4229",class:"controls-overlay"},o("div",{key:"880ba34f2650bb4eb59da0c4efbdeab1e218612e",class:"info"},o("div",{key:"69918a5f5996d62e6da92087765c4c85e258ee4f",class:"title"},"Ad Video from Google"),o("div",{key:"9278b8de8b7e2aec89b596c12e858c9358da5ac9",class:"description"},"Found on the web...")),o("div",{key:"acb43c9ed7fd285300244c3df93c40440adc33a3",class:"progress-bar"},o("input",{key:"2284a9a07bf435af8b80e1f16b6fe654b266337c",type:"range",ref:e=>this.seekElement=e,min:"0",max:"100",class:"seek",value:this.progressPercent,onChange:e=>this.handleSeek(e),onClickCapture:e=>this.inputSeek(e)})),o("div",{key:"4da6eac3a627fa0fcece4492555162f3b6425662",class:"controls"},o("div",{key:"1ab2d7fbaac122a98aaae5310d113e07856b57bb",class:"left"},o("button",{key:"9b3ef1094eaec87cff17f5159fc0a9a2e31fbd5c",onClick:()=>this.handlePlay()}),o("button",{key:"70b050babf342fb2ca91ca172b2868642724addd",onClick:()=>this.handlePause()})),o("div",{key:"4fee85bcaeb2d7504ee3f53e97e6a1da99fdbfda",class:"right"},o("button",{key:"a5b3363cfa522afc38abb6b20fc4205412a3ccdf",onClick:()=>this.handlePause()})))))}get el(){return t(this)}};a.style=n;export{a as nylas_video_player};
|
|
2
|
-
//# sourceMappingURL=p-3d93df74.entry.js.map
|