diff --git a/src/Umbraco.Web.UI.Client/gulp/tasks/dependencies.js b/src/Umbraco.Web.UI.Client/gulp/tasks/dependencies.js index 754962b3c7..5b4029386f 100644 --- a/src/Umbraco.Web.UI.Client/gulp/tasks/dependencies.js +++ b/src/Umbraco.Web.UI.Client/gulp/tasks/dependencies.js @@ -289,11 +289,6 @@ function dependencies() { "./node_modules/@umbraco-ui/uui-css/dist/uui-text.css" ], "base": "./node_modules/@umbraco-ui" - }, - { - "name": "sortablejs", - "src": ["./node_modules/sortablejs/Sortable.min.js"], - "base": "./node_modules/sortablejs" } ]; diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index 737b63ab1d..ec7589eca6 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -38,7 +38,6 @@ "moment": "2.29.4", "ng-file-upload": "12.2.13", "nouislider": "15.6.1", - "sortablejs": "1.15.0", "spectrum-colorpicker2": "2.0.9", "tinymce": "4.9.11", "typeahead.js": "0.11.1", @@ -15113,11 +15112,6 @@ "node": ">=0.10.0" } }, - "node_modules/sortablejs": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz", - "integrity": "sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w==" - }, "node_modules/source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", @@ -28961,11 +28955,6 @@ "sort-keys": "^1.0.0" } }, - "sortablejs": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.15.0.tgz", - "integrity": "sha512-bv9qgVMjUMf89wAvM6AxVvS/4MX3sPeN0+agqShejLU5z5GX4C75ow1O2e5k4L6XItUyAK3gH6AxSbXrOM5e8w==" - }, "source-map": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", diff --git a/src/Umbraco.Web.UI.Client/package.json b/src/Umbraco.Web.UI.Client/package.json index 8c4e691fcc..8d8334e3a7 100644 --- a/src/Umbraco.Web.UI.Client/package.json +++ b/src/Umbraco.Web.UI.Client/package.json @@ -49,7 +49,6 @@ "moment": "2.29.4", "ng-file-upload": "12.2.13", "nouislider": "15.6.1", - "sortablejs": "1.15.0", "spectrum-colorpicker2": "2.0.9", "tinymce": "4.9.11", "typeahead.js": "0.11.1", diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/blockgridentryeditors/gridinlineblock/gridinlineblock.editor.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/blockgridentryeditors/gridinlineblock/gridinlineblock.editor.html index 3a67a1be88..71c4da4178 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/blockgridentryeditors/gridinlineblock/gridinlineblock.editor.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/blockgridentryeditors/gridinlineblock/gridinlineblock.editor.html @@ -71,7 +71,11 @@ min-height: 48px; height: auto; } - + + .blockelement-gridinlineblock-editor > slot { + --umb-block-grid--inline-editor--pointer-events--condition: var(--umb-block-grid--dragging-mode) none; + pointer-events: var(--umb-block-grid--inline-editor--pointer-events--condition, auto); + } @@ -100,6 +104,6 @@ - + \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/blockgridui.less b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/blockgridui.less index b6205d73ac..c037631d46 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/blockgridui.less +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/blockgridui.less @@ -188,7 +188,8 @@ ng-form.ng-invalid-val-server-match-content > .umb-block-grid__block:not(.--acti &.--active { /** Avoid displaying hover when dragging-mode */ - --umb-block-grid--block-ui-opacity: calc(1 - var(--umb-block-grid--dragging-mode, 0)); + --umb-block-grid--block-ui-opacity--condition: var(--umb-block-grid--dragging-mode) 0; + --umb-block-grid--block-ui-opacity: var(--umb-block-grid--block-ui-opacity--code, 1); > .umb-block-grid__block--context { opacity: var(--umb-block-grid--block-ui-opacity); @@ -412,7 +413,9 @@ ng-form.ng-invalid > .umb-block-grid__block:not(.--active) > .umb-block-grid__bl z-index: 1; /** overwritten for the first one of an area. */ /** Avoid showing inline-create in dragging-mode */ - opacity: calc(1 - var(--umb-block-grid--dragging-mode, 0)); + + --umb-block-grid__block--inline-create-button-display--condition: var(--umb-block-grid--dragging-mode) none; + display: var(--umb-block-grid__block--inline-create-button-display--condition); } .umb-block-grid__block--inline-create-button.--above { left: 0; @@ -420,7 +423,7 @@ ng-form.ng-invalid > .umb-block-grid__block:not(.--active) > .umb-block-grid__bl top: calc(var(--umb-block-grid--row-gap, 0px) * -0.5); } -.umb-block-grid__layout-item:first-of-type .umb-block-grid__block--inline-create-button.--above { +.umb-block-grid__layout-item:first-of-type > .umb-block-grid__block--inline-create-button.--above { /* Do not use row-gap if the first one. */ top: 0; } @@ -454,6 +457,10 @@ ng-form.ng-invalid > .umb-block-grid__block:not(.--active) > .umb-block-grid__bl /* Move inline create button slightly up, to avoid collision with others*/ margin-bottom: -7px; margin-top: -13px; + + /** Avoid showing last-inline-create in dragging-mode */ + --umb-block-grid__block--last-inline-create-button-display--condition: var(--umb-block-grid--dragging-mode) none; + display: var(--umb-block-grid__block--last-inline-create-button-display--condition); } @@ -553,6 +560,7 @@ ng-form.ng-invalid > .umb-block-grid__block:not(.--active) > .umb-block-grid__bl .umb-block-grid__area-actions { grid-column: span var(--umb-block-grid--area-column-span); + flex-grow: 1; opacity: calc(var(--umb-block-grid--hint-area-ui, 0) * .5 + var(--umb-block-grid--show-area-ui, 0)); transition: opacity 120ms; @@ -590,10 +598,12 @@ ng-form.ng-invalid > .umb-block-grid__block:not(.--active) > .umb-block-grid__bl } } + .umb-block-grid__layout-item-placeholder { background: transparent; border-radius: 3px; + box-sizing: border-box; border: solid 1px; border-color: rgba(@blueDark, .5); border-radius: 3px; @@ -601,9 +611,11 @@ ng-form.ng-invalid > .umb-block-grid__block:not(.--active) > .umb-block-grid__bl height: 100%; } + .umb-block-grid__layout-item-placeholder > * { display: none; } + .umb-block-grid__layout-item-placeholder::before { content: ''; position:absolute; @@ -611,6 +623,7 @@ ng-form.ng-invalid > .umb-block-grid__block:not(.--active) > .umb-block-grid__bl inset: 0; border-radius: 3px; background-color: white; + pointer-events:none; } .umb-block-grid__layout-item-placeholder::after { content: ''; @@ -618,6 +631,7 @@ ng-form.ng-invalid > .umb-block-grid__block:not(.--active) > .umb-block-grid__bl z-index:1; inset: 0; border-radius: 3px; + pointer-events:none; transition: background-color 240ms ease-in; animation: umb-block-grid__placeholder__pulse 400ms ease-in-out alternate infinite; @@ -627,10 +641,14 @@ ng-form.ng-invalid > .umb-block-grid__block:not(.--active) > .umb-block-grid__bl } } - .umb-block-grid__area { position: relative; - --umb-block-grid--show-area-ui: 0; + height: 100%; + display: flex; + flex-direction: column; + + --umb-block-grid__area--show-area-ui--condition: var(--umb-block-grid--dragging-mode) 1; + --umb-block-grid--show-area-ui: var(--umb-block-grid__area--show-area-ui--condition, 0); } .umb-block-grid__area:focus, .umb-block-grid__area:focus-within, @@ -654,10 +672,9 @@ ng-form.ng-invalid > .umb-block-grid__block:not(.--active) > .umb-block-grid__bl /* Moved slightly in to align with the inline-create button, which is moved slightly in to avoid collision with other create buttons. */ top:2px; bottom: 2px; - /** Avoid displaying highlight when in dragging-mode */ - opacity: calc(1 - var(--umb-block-grid--dragging-mode, 0)); border-color: @blueDark; box-shadow: 0 0 0 1px rgba(255, 255, 255, .7), inset 0 0 0 1px rgba(255, 255, 255, .7); + } .umb-block-grid__area:has( .umb-block-grid__layout-item-placeholder )::after { opacity: 1; @@ -674,6 +691,9 @@ ng-form.ng-invalid > .umb-block-grid__block:not(.--active) > .umb-block-grid__bl 100% { border-color: rgba(@blueDark, 0.66); } } } +.umb-block-grid__area > ng-form { + display: contents; +} .umb-block-grid__scalebox-backdrop { position: absolute; diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/blockgrid.blockconfiguration.area.overlay.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/blockgrid.blockconfiguration.area.overlay.controller.js index f20f14f227..1c2f7e1c2b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/blockgrid.blockconfiguration.area.overlay.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/blockgrid.blockconfiguration.area.overlay.controller.js @@ -25,7 +25,7 @@ value: {min:vm.area.minAllowed, max:vm.area.maxAllowed} } - unsubscribe.push($scope.$watch('vm.area.alias', (newVal, oldVal) => { + unsubscribe.push($scope.$watch('vm.area.alias', (newVal) => { $scope.model.updateTitle(); if($scope.blockGridBlockConfigurationAreaForm.alias) { $scope.blockGridBlockConfigurationAreaForm.alias.$setValidity("alias", $scope.model.otherAreaAliases.indexOf(newVal) === -1); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/blockgrid.blockconfiguration.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/blockgrid.blockconfiguration.controller.js index 84a64a7669..3c005663e8 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/blockgrid.blockconfiguration.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/blockgrid.blockconfiguration.controller.js @@ -241,7 +241,6 @@ infiniteMode: true, noTemplate: true, isElement: true, - noTemplate: true, submit: function (model) { loadElementTypes().then( function () { callback(model.documentTypeKey); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/blockgrid.blockconfiguration.overlay.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/blockgrid.blockconfiguration.overlay.controller.js index 0bb9f6e703..11a0972309 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/blockgrid.blockconfiguration.overlay.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/blockgrid.blockconfiguration.overlay.controller.js @@ -93,7 +93,7 @@ var elementTypeId = elementType.id; const editor = { id: elementTypeId, - submit: function (model) { + submit: function () { editorService.close(); }, close: function () { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/umb-block-grid-area-editor.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/umb-block-grid-area-editor.html index 64a7909b7a..7ee2ee6344 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/umb-block-grid-area-editor.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/umb-block-grid-area-editor.html @@ -2,33 +2,40 @@ -
+
- -
+ +
diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/umb-block-grid-area-editor.less b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/umb-block-grid-area-editor.less index bf66c34661..4f5d45c67c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/umb-block-grid-area-editor.less +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/umb-block-grid-area-editor.less @@ -217,6 +217,9 @@ Grid part: display: flex; align-items: center; justify-content: center; + + height:50px; + width:100%; color: @ui-action-discreet-type; font-weight: bold; diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/umbBlockGridAreaAllowanceEditor.component.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/umbBlockGridAreaAllowanceEditor.component.js index 693cdcc223..9729ddd85b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/umbBlockGridAreaAllowanceEditor.component.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/umbBlockGridAreaAllowanceEditor.component.js @@ -27,7 +27,7 @@ } }); - function BlockGridAreaAllowanceController($scope, $element, assetsService, localizationService, editorService) { + function BlockGridAreaAllowanceController($scope) { var unsubscribe = []; diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/umbBlockGridAreaEditor.component.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/umbBlockGridAreaEditor.component.js index 9126a6cc54..3b9b6b4bea 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/umbBlockGridAreaEditor.component.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/umbBlockGridAreaEditor.component.js @@ -1,6 +1,44 @@ (function () { "use strict"; + + // Utils: + + function getInterpolatedIndexOfPositionInWeightMap(target, weights) { + const map = [0]; + weights.reduce((a, b, i) => { return map[i+1] = a+b; }, 0); + const foundValue = map.reduce((a, b) => { + let aDiff = Math.abs(a - target); + let bDiff = Math.abs(b - target); + + if (aDiff === bDiff) { + return a < b ? a : b; + } else { + return bDiff < aDiff ? b : a; + } + }) + const foundIndex = map.indexOf(foundValue); + const targetDiff = (target-foundValue); + let interpolatedIndex = foundIndex; + if (targetDiff < 0 && foundIndex === 0) { + // Don't adjust. + } else if (targetDiff > 0 && foundIndex === map.length-1) { + // Don't adjust. + } else { + const foundInterpolationWeight = weights[targetDiff >= 0 ? foundIndex : foundIndex-1]; + interpolatedIndex += foundInterpolationWeight === 0 ? interpolatedIndex : (targetDiff/foundInterpolationWeight) + } + return interpolatedIndex; + } + + function getAccumulatedValueOfIndex(index, weights) { + let i = 0, len = Math.min(index, weights.length), calc = 0; + while(i modelEntry.key === el.dataset.areaKey, + querySelectModelToElement: (container, modelEntry) => container.querySelector(`[data-area-key='${modelEntry.key}']`), + itemHasNestedContainersResolver: () => false,// We never have nested in this case. + containerSelector: ".umb-block-grid-area-editor__grid-wrapper", + itemSelector: ".umb-block-grid-area-editor__area", + placeholderClass: "umb-block-grid-area-editor__area-placeholder", + onSync: onSortSync } - const gridContainerEl = $element[0].querySelector('.umb-block-grid-area-editor__grid-wrapper'); + function onSortSync() { + $scope.$evalAsync(); + setDirty(); + } - const sortable = Sortable.create(gridContainerEl, { - sort: true, // sorting inside list - animation: 150, // ms, animation speed moving items when sorting, `0` — without animation - easing: "cubic-bezier(1, 0, 0, 1)", // Easing for animation. Defaults to null. See https://easings.net/ for examples. - cancel: '', - draggable: ".umb-block-grid-area-editor__area", // Specifies which items inside the element should be draggable - ghostClass: "umb-block-grid-area-editor__area-placeholder", - onAdd: function (evt) { - _sync(evt); - $scope.$evalAsync(); - }, - onUpdate: function (evt) { - _sync(evt); - $scope.$evalAsync(); + function resolveVerticalDirection(data) { + + /** We need some data about the grid to figure out if there is room to be placed next to the found element */ + const approvedContainerComputedStyles = getComputedStyle(data.containerElement); + const gridColumnGap = Number(approvedContainerComputedStyles.columnGap.split("px")[0]) || 0; + const gridColumnNumber = vm.rootLayoutColumns; + + const foundElColumns = parseInt(data.relatedElement.dataset.colSpan, 10); + const currentElementColumns = data.item.columnSpan; + + if(currentElementColumns >= gridColumnNumber) { + return true; } - }); - - // TODO: setDirty if sort has happend. + + // Get grid template: + const approvedContainerGridColumns = approvedContainerComputedStyles.gridTemplateColumns.trim().split("px").map(x => Number(x)).filter(n => n > 0).map((n, i, list) => list.length === i ? n : n + gridColumnGap); + + // ensure all columns are there. + // This will also ensure handling non-css-grid mode, + // use container width divided by amount of columns( or the item width divided by its amount of columnSpan) + let amountOfColumnsInWeightMap = approvedContainerGridColumns.length; + const amountOfUnknownColumns = gridColumnNumber-amountOfColumnsInWeightMap; + if(amountOfUnknownColumns > 0) { + let accumulatedValue = getAccumulatedValueOfIndex(amountOfColumnsInWeightMap, approvedContainerGridColumns) || 0; + const layoutWidth = data.containerRect.width; + const missingColumnWidth = (layoutWidth-accumulatedValue)/amountOfUnknownColumns; + if(missingColumnWidth > 0) { + while(amountOfColumnsInWeightMap++ < gridColumnNumber) { + approvedContainerGridColumns.push(missingColumnWidth); + } + } + } + + let offsetPlacement = 0; + /* If placeholder is in this same line, we want to assume that it will offset the placement of the found element, + which provides more potential space for the item to drop at. + This is relevant in this calculation where we look at the space to determine if its a vertical or horizontal drop in relation to the found element. + */ + if(data.placeholderIsInThisRow && data.elementRect.left < data.relatedRect.left) { + offsetPlacement = -(data.elementRect.width + gridColumnGap); + } + + const relatedStartX = Math.max(data.relatedRect.left - data.containerRect.left + offsetPlacement, 0); + const relatedStartCol = Math.round(getInterpolatedIndexOfPositionInWeightMap(relatedStartX, approvedContainerGridColumns)); + + // If the found related element does not have enough room after which for the current element, then we go vertical mode: + return (relatedStartCol + (data.horizontalPlaceAfter ? foundElColumns : 0) + currentElementColumns > gridColumnNumber); + + } + } diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/umbBlockGridColumnEditor.component.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/umbBlockGridColumnEditor.component.js index 864f479009..1dcbc5b2da 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/umbBlockGridColumnEditor.component.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/prevalue/umbBlockGridColumnEditor.component.js @@ -25,9 +25,7 @@ } }); - function BlockGridColumnController($scope) { - - //var unsubscribe = []; + function BlockGridColumnController() { var vm = this; @@ -58,12 +56,6 @@ } } - /*$scope.$on("$destroy", function () { - for (const subscription of unsubscribe) { - subscription(); - } - });*/ - } })(); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/umb-block-grid-entries.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/umb-block-grid-entries.html index 4aed670ffd..ef02d28318 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/umb-block-grid-entries.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/blockgrid/umb-block-grid-entries.html @@ -2,9 +2,10 @@