@blockly/continuous-toolbox
Version:
A Blockly plugin that adds a continous-scrolling style toolbox and flyout
3 lines • 9.8 kB
JavaScript
/*! For license information please see index.js.LICENSE.txt */
!function(t,e){if("object"==typeof exports&&"object"==typeof module)module.exports=e(require("blockly/core"));else if("function"==typeof define&&define.amd)define(["blockly/core"],e);else{var o="object"==typeof exports?e(require("blockly/core")):e(t.Blockly);for(var s in o)("object"==typeof exports?exports:t)[s]=o[s]}}(this,(t=>(()=>{"use strict";var e={370:e=>{e.exports=t}},o={};function s(t){var i=o[t];if(void 0!==i)return i.exports;var r=o[t]={exports:{}};return e[t](r,r.exports,s),r.exports}s.d=(t,e)=>{for(var o in e)s.o(e,o)&&!s.o(t,o)&&Object.defineProperty(t,o,{enumerable:!0,get:e[o]})},s.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),s.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var i={};s.r(i),s.d(i,{ContinuousCategory:()=>l,ContinuousFlyout:()=>a,ContinuousMetrics:()=>h,ContinuousToolbox:()=>g,RecyclableBlockFlyoutInflater:()=>c,registerContinuousToolbox:()=>u});var r=s(370);class l extends r.ToolboxCategory{createLabelDom_(t){var e;const o=document.createElement("div");return o.setAttribute("id",this.getId()+".label"),o.textContent=t,o.classList.add(null!==(e=this.cssConfig_.label)&&void 0!==e?e:""),o}createIconDom_(){const t=document.createElement("div");return t.classList.add("categoryBubble"),t.style.backgroundColor=this.colour_,t}addColourBorder_(){}setSelected(t){var e,o;this.rowDiv_&&this.htmlDiv_&&(t?(this.rowDiv_.style.backgroundColor="gray",r.utils.dom.addClass(this.rowDiv_,null!==(e=this.cssConfig_.selected)&&void 0!==e?e:"")):(this.rowDiv_.style.backgroundColor="",r.utils.dom.removeClass(this.rowDiv_,null!==(o=this.cssConfig_.selected)&&void 0!==o?o:"")),r.utils.aria.setState(this.htmlDiv_,r.utils.aria.State.SELECTED,t))}}class n extends r.FlyoutMetricsManager{getScrollMetrics(t,e,o){const s=super.getScrollMetrics(t,e,o),i=o||this.getContentMetrics(t),r=e||this.getViewMetrics(t);return s&&(s.height+=this.flyout_.calculateBottomPadding(i,r)),s}}class c extends r.BlockFlyoutInflater{constructor(){super(...arguments),this.recyclingEnabled=!1,this.recycledBlocks=new Map}createBlock(t,e){var o;const s=this.getTypeFromDefinition(t);return null!==(o=this.getRecycledBlock(s))&&void 0!==o?o:super.createBlock(t,e)}getTypeFromDefinition(t){let e;if(e=t.blockxml?("string"==typeof t.blockxml?r.utils.xml.textToDom(t.blockxml):t.blockxml).getAttribute("type"):t.type,!e)throw new Error(`Block type is not specified in block definition: ${JSON.stringify(t)}`);return e}recycleBlock(t){const e=t.getRelativeToSurfaceXY();t.moveBy(-e.x,-e.y),this.recycledBlocks.set(t.type,t)}getRecycledBlock(t){const e=this.recycledBlocks.get(t);return this.recycledBlocks.delete(t),e}blockIsRecyclable(t){if(!this.recyclingEnabled)return!1;if(this.recycleEligibilityChecker)return this.recycleEligibilityChecker(t);if(t.mutationToDom||t.domToMutation||t.saveExtraState||t.loadExtraState)return!1;if(!t.isEnabled())return!1;for(const e of t.inputList){for(const t of e.fieldRow){if(t.referencesVariables())return!1;if(t instanceof r.FieldDropdown&&t.isOptionListDynamic())return!1}if(e.connection){const t=e.connection.targetBlock();if(t&&!this.blockIsRecyclable(t))return!1}}return!0}disposeItem(t){const e=t.getElement();e instanceof r.BlockSvg&&this.blockIsRecyclable(e)?(this.removeListeners(e.id),this.recycleBlock(e)):super.disposeItem(t)}emptyRecycledBlocks(){this.recycledBlocks.forEach((t=>t.dispose(!1,!1))),this.recycledBlocks.clear()}}class a extends r.VerticalFlyout{constructor(t){super(t),this.scrollPositions=new Map,this.scrollAnimationFraction=.3,this.autoClose=!1,this.getWorkspace().setMetricsManager(new n(this.getWorkspace(),this)),this.getWorkspace().addChangeListener((t=>{t.type===r.Events.VIEWPORT_CHANGE&&this.selectCategoryByScrollPosition(-this.getWorkspace().scrollY)})),this.setRecyclingEnabled(!0)}getParentToolbox(){return this.targetWorkspace.getToolbox()}recordScrollPositions(){this.scrollPositions.clear(),this.getContents().filter(this.toolboxItemIsLabel.bind(this)).map((t=>t.getElement())).forEach((t=>{this.scrollPositions.set(t.getButtonText(),Math.max(0,t.getPosition().y-this.GAP_Y/2))}))}toolboxItemIsLabel(t){const e=t.getElement();return!!("label"===t.getType()&&e instanceof r.FlyoutButton&&e.isLabel()&&this.getParentToolbox().getCategoryByName(e.getButtonText()))}getCategoryScrollPosition(t){const e=this.scrollPositions.get(t);return void 0===e&&console.warn(`Scroll position not recorded for category ${t}`),null!=e?e:null}selectCategoryByScrollPosition(t){if(this.scrollTarget)return;const e=Math.round(t/this.getWorkspace().scale);for(const[t,o]of[...this.scrollPositions.entries()].reverse())if(e>=o)return void this.getParentToolbox().selectCategoryByName(t)}scrollTo(t){const e=this.getWorkspace().getMetrics();this.scrollTarget=Math.min(t*this.getWorkspace().scale,e.scrollHeight-e.viewHeight),this.stepScrollAnimation()}scrollToCategory(t){const e=this.scrollPositions.get(t.getName());void 0!==e?this.scrollTo(e):console.warn(`Scroll position not recorded for category ${name}`)}stepScrollAnimation(){var t,e;if(void 0===this.scrollTarget)return;const o=-this.getWorkspace().scrollY,s=this.scrollTarget-o;if(Math.abs(s)<1)return null===(t=this.getWorkspace().scrollbar)||void 0===t||t.setY(this.scrollTarget),void(this.scrollTarget=void 0);null===(e=this.getWorkspace().scrollbar)||void 0===e||e.setY(o+s*this.scrollAnimationFraction),requestAnimationFrame(this.stepScrollAnimation.bind(this))}wheel_(t){this.scrollTarget||super.wheel_(t)}calculateBottomPadding(t,e){var o;if(0===this.scrollPositions.size)return 0;const s=(null!==(o=[...this.scrollPositions.values()].pop())&&void 0!==o?o:0)*this.getWorkspace().scale,i=t.height-s;return i<e.height?e.height-i:0}getX(){return this.isVisible()&&this.targetWorkspace.toolboxPosition===this.toolboxPosition_&&this.targetWorkspace.getToolbox()&&this.toolboxPosition_!==r.utils.toolbox.Position.LEFT?this.targetWorkspace.getMetricsManager().getViewMetrics().width:super.getX()}show(t){super.show(t),this.recordScrollPositions(),this.getWorkspace().resizeContents(),this.getParentToolbox().getSelectedItem()||this.selectCategoryByScrollPosition(0),this.getRecyclableInflater().emptyRecycledBlocks()}setBlockIsRecyclable(t){this.getRecyclableInflater().recycleEligibilityChecker=t}setRecyclingEnabled(t){this.getRecyclableInflater().recyclingEnabled=t}getRecyclableInflater(){const t=this.getInflaterForType("block");if(!(t instanceof c))throw new Error("The RecyclableBlockFlyoutInflater is not registered.");return t}}class h extends r.MetricsManager{getViewMetrics(t=!1){const e=t?this.workspace_.scale:1,o=this.getSvgMetrics(),s=this.getToolboxMetrics(),i=this.getFlyoutMetrics(!1),l=s.position;return this.workspace_.getToolbox()&&(l==r.TOOLBOX_AT_TOP||l==r.TOOLBOX_AT_BOTTOM?o.height-=s.height+i.height:l!=r.TOOLBOX_AT_LEFT&&l!=r.TOOLBOX_AT_RIGHT||(o.width-=s.width+i.width)),{height:o.height/e,width:o.width/e,top:-this.workspace_.scrollY/e,left:-this.workspace_.scrollX/e}}getAbsoluteMetrics(){const t=this.getToolboxMetrics(),e=this.getFlyoutMetrics(!1),o=t.position;let s=0;this.workspace_.getToolbox()&&o==r.TOOLBOX_AT_LEFT&&(s=t.width+e.width);let i=0;return this.workspace_.getToolbox()&&o==r.TOOLBOX_AT_TOP&&(i=t.height+e.height),{top:i,left:s}}}class g extends r.Toolbox{init(){super.init(),this.getFlyout().show(this.getInitialFlyoutContents()),this.getWorkspace().addChangeListener((t=>{t.type!==r.Events.BLOCK_CREATE&&t.type!==r.Events.BLOCK_DELETE&&t.type!==r.Events.BLOCK_CHANGE||this.refreshSelection()}))}getFlyout(){return super.getFlyout()}getInitialFlyoutContents(){return this.getToolboxItems().flatMap(this.convertToolboxItemToFlyoutItems)}convertToolboxItemToFlyoutItems(t){let e=[];if(t instanceof r.ToolboxCategory){e.push({kind:"LABEL",text:t.getName()});let o=t.getContents();"string"==typeof o&&(o=[{custom:o,kind:"CATEGORY"}]),e=e.concat(o)}return e}refreshSelection(){this.getFlyout().isVisible()&&(this.refreshDebouncer&&clearTimeout(this.refreshDebouncer),this.refreshDebouncer=setTimeout((()=>{this.getFlyout().show(this.getInitialFlyoutContents())}),100))}updateFlyout_(t,e){e?(this.getFlyout().scrollToCategory(e),this.getFlyout().isVisible()||this.getFlyout().show(this.getInitialFlyoutContents())):this.getFlyout().autoClose&&this.getFlyout().hide()}shouldDeselectItem_(t,e){return!(!t||t===e)}getCategoryByName(t){return this.getToolboxItems().find((e=>e instanceof r.ToolboxCategory&&e.isSelectable()&&t===e.getName()))||null}selectCategoryByName(t){const e=this.getCategoryByName(t);if(!e)return;const o=this.selectedItem_;o&&this.shouldDeselectItem_(o,e)&&this.deselectItem_(o),this.shouldSelectItem_(o,e)&&this.selectItem_(o,e)}getClientRect(){const t=this.getFlyout();return t&&!t.autoClose?t.getClientRect():super.getClientRect()}}function u(){r.registry.register(r.registry.Type.TOOLBOX_ITEM,r.ToolboxCategory.registrationName,l,!0),r.registry.register(r.registry.Type.METRICS_MANAGER,"ContinuousMetrics",h,!0),r.registry.register(r.registry.Type.FLYOUTS_VERTICAL_TOOLBOX,"ContinuousFlyout",a,!0),r.registry.register(r.registry.Type.TOOLBOX,"ContinuousToolbox",g,!0),r.registry.register(r.registry.Type.FLYOUT_INFLATER,"block",c,!0),r.Css.register("\n .categoryBubble {\n margin: 0 auto 0.125rem;\n border-radius: 100%;\n border: 1px solid;\n width: 1.25rem;\n height: 1.25rem;\n }\n .blocklyToolboxCategory {\n height: initial;\n padding: 3px 0;\n }\n .blocklyTreeRowContentContainer {\n display: flex;\n flex-direction: column;\n }\n .blocklyTreeLabel {\n margin: auto;\n }\n .blocklyToolboxCategoryLabel {\n text-align: center;\n }\n ")}return i})()));
//# sourceMappingURL=index.js.map