改进鼠标选框

This commit is contained in:
Wisp X 2021-12-25 09:18:31 +08:00
parent 5cd405ea7c
commit f326f74b76
8 changed files with 1105 additions and 1089 deletions

2033
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -20,7 +20,7 @@
"blueimp-load-image": "^5.16.0",
"clipboard": "^2.0.8",
"deepmerge": "^4.2.2",
"dragselect": "^2.2.2",
"dragselect": "^2.3.0",
"jquery": "^3.6.0",
"jquery.photoswipe": "^1.1.1",
"justifiedGallery": "^3.8.1",

96
public/css/app.css vendored
View File

@ -1,5 +1,5 @@
/*
! tailwindcss v3.0.0 | MIT License | https://tailwindcss.com
! tailwindcss v3.0.7 | MIT License | https://tailwindcss.com
*//*
1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4)
2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116)
@ -148,7 +148,7 @@ sup {
table {
text-indent: 0; /* 1 */
border-color: inherit; /* 2 */
border-collapse: collapse; /* 3 */
border-collapse: collapse; /* 3 */
}
/*
@ -313,18 +313,18 @@ textarea {
*/
input::-moz-placeholder, textarea::-moz-placeholder {
opacity: 1; /* 1 */
opacity: 1; /* 1 */
color: #9ca3af; /* 2 */
}
input:-ms-input-placeholder, textarea:-ms-input-placeholder {
opacity: 1; /* 1 */
opacity: 1; /* 1 */
color: #9ca3af; /* 2 */
}
input::placeholder,
textarea::placeholder {
opacity: 1; /* 1 */
opacity: 1; /* 1 */
color: #9ca3af; /* 2 */
}
@ -380,53 +380,6 @@ Ensure the default browser behavior of the `hidden` attribute.
display: none;
}
.scale-95, .scale-100, .transform {
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-transform: translateX(var(--tw-translate-x)) translateY(var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}
.divide-y > *, .border, .border-2, .border-0, .border-b-2, .border-b, .border-t, .border-r {
--tw-border-opacity: 1;
border-color: rgb(229 231 235 / var(--tw-border-opacity));
}
.shadow-sm, .shadow-lg, .shadow, .sm\:shadow-none {
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
}
.ring-1, .focus\:ring, .focus\:ring-2 {
--tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
}
.filter {
--tw-blur: var(--tw-empty,/*!*/ /*!*/);
--tw-brightness: var(--tw-empty,/*!*/ /*!*/);
--tw-contrast: var(--tw-empty,/*!*/ /*!*/);
--tw-grayscale: var(--tw-empty,/*!*/ /*!*/);
--tw-hue-rotate: var(--tw-empty,/*!*/ /*!*/);
--tw-invert: var(--tw-empty,/*!*/ /*!*/);
--tw-saturate: var(--tw-empty,/*!*/ /*!*/);
--tw-sepia: var(--tw-empty,/*!*/ /*!*/);
--tw-drop-shadow: var(--tw-empty,/*!*/ /*!*/);
--tw-filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}
[type='text'],[type='email'],[type='url'],[type='password'],[type='number'],[type='date'],[type='datetime-local'],[type='month'],[type='search'],[type='tel'],[type='time'],[type='week'],[multiple],textarea,select {
-webkit-appearance: none;
-moz-appearance: none;
@ -592,6 +545,36 @@ select {
[type='file']:focus {
outline: 1px auto -webkit-focus-ring-color;
}
*, ::before, ::after {
--tw-translate-x: 0;
--tw-translate-y: 0;
--tw-rotate: 0;
--tw-skew-x: 0;
--tw-skew-y: 0;
--tw-scale-x: 1;
--tw-scale-y: 1;
--tw-transform: translateX(var(--tw-translate-x)) translateY(var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
--tw-border-opacity: 1;
border-color: rgb(229 231 235 / var(--tw-border-opacity));
--tw-ring-inset: var(--tw-empty,/*!*/ /*!*/);
--tw-ring-offset-width: 0px;
--tw-ring-offset-color: #fff;
--tw-ring-color: rgb(59 130 246 / 0.5);
--tw-ring-offset-shadow: 0 0 #0000;
--tw-ring-shadow: 0 0 #0000;
--tw-shadow: 0 0 #0000;
--tw-shadow-colored: 0 0 #0000;
--tw-blur: var(--tw-empty,/*!*/ /*!*/);
--tw-brightness: var(--tw-empty,/*!*/ /*!*/);
--tw-contrast: var(--tw-empty,/*!*/ /*!*/);
--tw-grayscale: var(--tw-empty,/*!*/ /*!*/);
--tw-hue-rotate: var(--tw-empty,/*!*/ /*!*/);
--tw-invert: var(--tw-empty,/*!*/ /*!*/);
--tw-saturate: var(--tw-empty,/*!*/ /*!*/);
--tw-sepia: var(--tw-empty,/*!*/ /*!*/);
--tw-drop-shadow: var(--tw-empty,/*!*/ /*!*/);
--tw-filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}
.container {
width: 100%;
}
@ -1418,7 +1401,8 @@ select {
color: rgb(71 85 105 / var(--tw-text-opacity));
}
.underline {
text-decoration: underline;
-webkit-text-decoration-line: underline;
text-decoration-line: underline;
}
.antialiased {
-webkit-font-smoothing: antialiased;
@ -1490,9 +1474,9 @@ select {
filter: var(--tw-filter);
}
.transition {
transition-property: background-color, border-color, color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
transition-property: background-color, border-color, color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
transition-property: background-color, border-color, color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
transition-property: color, background-color, border-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-text-decoration-color, -webkit-backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-text-decoration-color, -webkit-backdrop-filter;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
transition-duration: 150ms;
}

14
public/css/common.css vendored
View File

@ -272,19 +272,19 @@ progress::-webkit-progress-value {
color: grey;
}
#photos-grid a:hover,
#photos-grid a.selected {
#photos-grid a.ds-selected {
outline-color: #3b82f6;
}
#photos-grid a:hover .photo-select,
#photos-grid a.selected .photo-select {
#photos-grid a:hover .photo-selector,
#photos-grid a.ds-selected .photo-selector {
display: block;
}
#photos-grid a:hover.selected .photo-select,
#photos-grid a.selected.selected .photo-select {
#photos-grid a:hover.ds-selected .photo-selector,
#photos-grid a.ds-selected.ds-selected .photo-selector {
border-color: white;
}
#photos-grid a:hover.selected .photo-select > i,
#photos-grid a.selected.selected .photo-select > i {
#photos-grid a:hover.ds-selected .photo-selector > i,
#photos-grid a.ds-selected.ds-selected .photo-selector > i {
color: #0061ff;
}

14
public/js/app.js vendored
View File

@ -2069,7 +2069,7 @@ function setStylesFromString(el, value) {
let cache = el.getAttribute("style", value);
el.setAttribute("style", value);
return () => {
el.setAttribute("style", cache);
el.setAttribute("style", cache || "");
};
}
function kebabCase(subject) {
@ -2491,7 +2491,7 @@ var Alpine = {
get raw() {
return raw;
},
version: "3.7.0",
version: "3.7.1",
flushAndStopDeferringMutations,
disableEffectScheduling,
setReactivityEngine,
@ -2542,8 +2542,7 @@ magic("watch", (el) => (key, callback) => {
let firstTime = true;
let oldValue;
effect(() => evaluate2((value) => {
let div = document.createElement("div");
div.dataset.throwAway = value;
JSON.stringify(value);
if (!firstTime) {
queueMicrotask(() => {
callback(value, oldValue);
@ -2625,7 +2624,11 @@ magic("el", (el) => el);
// packages/alpinejs/src/directives/x-teleport.js
directive("teleport", (el, {expression}, {cleanup}) => {
if (el.tagName.toLowerCase() !== "template")
warn("x-teleport can only be used on a <template> tag", el);
let target = document.querySelector(expression);
if (!target)
warn(`Cannot find x-teleport element for selector: "${expression}"`);
let clone2 = el.content.cloneNode(true).firstElementChild;
el._x_teleport = clone2;
clone2._x_teleportBack = el;
@ -3063,9 +3066,6 @@ function applyBindingsObject(el, expression, original, effect3) {
cleanupRunners.pop()();
getBindings((bindings) => {
let attributes = Object.entries(bindings).map(([name, value]) => ({name, value}));
attributes = attributes.filter((attr) => {
return !(typeof attr.value === "object" && !Array.isArray(attr.value) && attr.value !== null);
});
let staticAttributes = attributesOnly(attributes);
attributes = attributes.map((attribute) => {
if (staticAttributes.find((attr) => attr.name === attribute.name)) {

File diff suppressed because one or more lines are too long

View File

@ -74,15 +74,15 @@ progress::-webkit-progress-value {
// 我的图片
#photos-grid {
a:hover, a.selected {
a:hover, a.ds-selected {
outline-color: #3b82f6;
.photo-select {
.photo-selector {
display: block;
}
&.selected {
.photo-select {
&.ds-selected {
.photo-selector {
border-color: white;
& > i {

View File

@ -65,7 +65,7 @@
<script type="text/html" id="photos-item">
<a href="javascript:void(0)" class="photos-item relative cursor-default rounded outline outline-2 outline-offset-2 outline-transparent">
<div class="photo-select absolute z-[1] top-1 right-1 rounded-full overflow-hidden text-white text-lg bg-white border border-gray-500 cursor-pointer hidden group-hover:block">
<div class="photo-selector absolute z-[1] top-1 right-1 rounded-full overflow-hidden text-white text-lg bg-white border border-gray-500 cursor-pointer hidden group-hover:block">
<i class="fas fa-check-circle block"></i>
</div>
<div class="photo-mask absolute left-0 right-0 bottom-0 h-20 z-[1] bg-gradient-to-t from-black">
@ -232,27 +232,18 @@
</script>
<script>
const ds = new DragSelect({
area: document.getElementById('photos-grid'),
area: $photos.get(0),
keyboardDrag: false,
// multiSelectMode: true,
// multiSelectToggling: false,
});
// 预期使用组件内部 api 实现单击选择图标进行选择/反选,但是 click 事件总在组件的 mousedown 事件后触发。
// 并且组件没有提供跳过某个元素选择的 api只能通过组件选框然后自定义 class 来判断选中项目。
// see https://github.com/ThibaultJanBeyer/DragSelect/issues/113#issuecomment-1000904432
// TODO 可能有更优的解决方案?
ds.subscribe('dragstart', ({ event }) => {
if ($(event.target).hasClass('justified-gallery')) {
$photos.find('a.photos-item').removeClass('selected');
ds.subscribe('predragstart', ({ event }) => {
if (event.target.id !== 'photos-grid') {
ds.break();
}
});
ds.subscribe('dragmove', ({ items, event}) => {
$(items).addClass('selected');
});
$photos.on('click', '.photo-select', function (e) {
$(this).closest('a.photos-item').toggleClass('selected');
});
$photos.on('click', '.photo-selector', function () {
ds.toggleSelection($(this).closest('a'));
})
</script>
@endpush
</x-app-layout>