Add image selection
This commit is contained in:
parent
cfdc78ab4c
commit
213d2b1559
@ -16,7 +16,7 @@
|
|||||||
"domvm": "~3.2.1",
|
"domvm": "~3.2.1",
|
||||||
"exif-parser": "~0.1.9",
|
"exif-parser": "~0.1.9",
|
||||||
"extract-text-webpack-plugin": "^3.0.2",
|
"extract-text-webpack-plugin": "^3.0.2",
|
||||||
"frptools": "2.1.0",
|
"frptools": "2.2.0",
|
||||||
"pica": "~2.0.8",
|
"pica": "~2.0.8",
|
||||||
"pouchdb-adapter-http": "~6.3.4",
|
"pouchdb-adapter-http": "~6.3.4",
|
||||||
"pouchdb-adapter-idb": "~6.3.4",
|
"pouchdb-adapter-idb": "~6.3.4",
|
||||||
|
|||||||
@ -1,9 +1,15 @@
|
|||||||
import { prop, computed } from 'frptools';
|
import { prop, computed, container } from 'frptools';
|
||||||
|
|
||||||
import { subscribeToRender, defineView, defineElement as el } from '../utils/domvm.js';
|
import {
|
||||||
|
subscribeToRender,
|
||||||
|
defineView,
|
||||||
|
subscribeToRender,
|
||||||
|
defineElement as el
|
||||||
|
} from '../utils/domvm.js';
|
||||||
|
|
||||||
|
import { error } from '../services/console.js';
|
||||||
import { ImageType } from '../data/image.js';
|
import { ImageType } from '../data/image.js';
|
||||||
import { pouchDocArrayHash, pouchDocHash } from '../utils/conversion.js';
|
import { pouchDocArrayHash, pouchDocHash, hashSet, extractID } from '../utils/conversion.js';
|
||||||
import { AlbumTemplate } from './components/albumTemplate.js';
|
import { AlbumTemplate } from './components/albumTemplate.js';
|
||||||
import { injectStyle, styled } from '../services/style.js';
|
import { injectStyle, styled } from '../services/style.js';
|
||||||
|
|
||||||
@ -17,7 +23,11 @@ export function uploadImages(evt, files) {
|
|||||||
|
|
||||||
export function AllImagesView(vm, params, key, opts) {
|
export function AllImagesView(vm, params, key, opts) {
|
||||||
const model = prop({}, pouchDocHash);
|
const model = prop({}, pouchDocHash);
|
||||||
const images = prop([], pouchDocArrayHash);
|
const images = container([], pouchDocArrayHash);
|
||||||
|
const visibleIds = computed(arr => arr.map(extractID), [images]);
|
||||||
|
const hoverId = prop(null);
|
||||||
|
const selectedIds = container(new Set(), hashSet);
|
||||||
|
const mode = computed(sIds => (sIds.size > 0 ? 'select' : 'view'), [selectedIds]);
|
||||||
|
|
||||||
ImageType.find(
|
ImageType.find(
|
||||||
{
|
{
|
||||||
@ -26,7 +36,7 @@ export function AllImagesView(vm, params, key, opts) {
|
|||||||
true
|
true
|
||||||
).then(la => {
|
).then(la => {
|
||||||
opts.appbar.renderButtons(renderAppBarButtons);
|
opts.appbar.renderButtons(renderAppBarButtons);
|
||||||
subscribeToRender(vm, [images], [la.subscribe(images)]);
|
subscribeToRender(vm, [images], [la.subscribe(res => images.splice(0, images.length, ...res))]);
|
||||||
});
|
});
|
||||||
|
|
||||||
function renderAppBarButtons() {
|
function renderAppBarButtons() {
|
||||||
@ -43,27 +53,74 @@ export function AllImagesView(vm, params, key, opts) {
|
|||||||
})
|
})
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
//
|
||||||
|
// function deleteImage(i) {
|
||||||
|
// ImageType.delete(i._id);
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// function addAlbum() {
|
||||||
|
// const albumName = prompt("Album Name");
|
||||||
|
// if (albumName && albumName.trim()) {
|
||||||
|
// const a = new AlbumType({
|
||||||
|
// title: albumName.trim(),
|
||||||
|
// count: 0
|
||||||
|
// });
|
||||||
|
// a.save();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
function deleteImage(i) {
|
function nodeParentWithType(node, type) {
|
||||||
ImageType.delete(i._id);
|
let parentNode = node;
|
||||||
|
while (parentNode && (!parentNode.data || parentNode.data.type !== type)) {
|
||||||
|
parentNode = parentNode.parent;
|
||||||
|
}
|
||||||
|
if (!parentNode) {
|
||||||
|
error(`Could not find {"type": "${type}"} parent.`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return parentNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
function addAlbum() {
|
function toggleSelect(evt, node, vm) {
|
||||||
const albumName = prompt('Album Name');
|
const imageNode = nodeParentWithType(node, 'image');
|
||||||
if (albumName && albumName.trim()) {
|
const id = imageNode.data._id;
|
||||||
const a = new AlbumType({
|
if (selectedIds.has(id)) {
|
||||||
title: albumName.trim(),
|
selectedIds.delete(id);
|
||||||
count: 0
|
} else {
|
||||||
});
|
selectedIds.add(id);
|
||||||
a.save();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toggleAll(evt, node, vm) {
|
||||||
|
if (images.length === selectedIds.size) {
|
||||||
|
selectedIds.clear();
|
||||||
|
} else {
|
||||||
|
images.map(extractID).forEach(i => selectedIds.add(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribeToRender(vm, [selectedIds, images, hoverId, mode]);
|
||||||
|
|
||||||
return function() {
|
return function() {
|
||||||
return AlbumTemplate({
|
return el(
|
||||||
|
'.eventSnarfer',
|
||||||
|
{
|
||||||
|
onclick: {
|
||||||
|
'.photoSelect .icon svg path': toggleSelect,
|
||||||
|
'.photoSelect .icon': toggleSelect,
|
||||||
|
'.albumSelectButton .icon': toggleAll,
|
||||||
|
'.albumSelectButton .icon svg path': toggleAll
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[
|
||||||
|
AlbumTemplate({
|
||||||
title: 'Test',
|
title: 'Test',
|
||||||
id: 1,
|
id: 1,
|
||||||
photos: images()
|
photos: images,
|
||||||
});
|
selectedIds,
|
||||||
|
mode: mode()
|
||||||
|
})
|
||||||
|
]
|
||||||
|
);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,66 +1,77 @@
|
|||||||
|
import { prop } from 'frptools';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
defineView as vw,
|
defineView as vw,
|
||||||
defineElement as el,
|
defineElement as el,
|
||||||
patchRefStyleMap,
|
patchRefStyleMap,
|
||||||
patchNodeStyle
|
patchNodeStyle,
|
||||||
|
subscribeToRender
|
||||||
} from '../../utils/domvm.js';
|
} from '../../utils/domvm.js';
|
||||||
import { injectStyle, styled } from '../../services/style.js';
|
import { injectStyle, styled } from '../../services/style.js';
|
||||||
|
import { DEFAULT_TRANSITION, CSS_FULL_SIZE, IMAGE_MARGIN } from '../styles.js';
|
||||||
import { Icon } from './icon.js';
|
import { Icon } from './icon.js';
|
||||||
import { AttachmentImageView } from './attachmentImage.js';
|
import { AttachmentImageView } from './attachmentImage.js';
|
||||||
|
|
||||||
export function AlbumPhotoTemplate(doc, isSelected, selectMode) {
|
const _imageHover = false;
|
||||||
|
const dim = 'opacity: 0.7;';
|
||||||
|
const off = 'opacity: 0;';
|
||||||
|
const full = 'opacity: 1;';
|
||||||
|
|
||||||
|
export function AlbumPhotoTemplate(vm, { doc }) {
|
||||||
const photoSelectButtonRef = `pSB${doc._id}`;
|
const photoSelectButtonRef = `pSB${doc._id}`;
|
||||||
const photoBackgroundRef = `pBkd${doc._id}`;
|
const photoBackgroundRef = `pBkd${doc._id}`;
|
||||||
|
const hover = prop(false);
|
||||||
|
const hoverSelectButton = prop(false);
|
||||||
|
|
||||||
|
subscribeToRender(vm, [hover, hoverSelectButton]);
|
||||||
|
|
||||||
|
return function render(vm, { isSelected, selectMode }) {
|
||||||
return photoContainer(
|
return photoContainer(
|
||||||
{
|
{
|
||||||
onmouseenter: [
|
class: 'photoContainer',
|
||||||
patchRefStyleMap,
|
onmouseenter: [hover, true],
|
||||||
{ [photoSelectButtonRef]: 'opacity: 0.7;', [photoBackgroundRef]: 'opacity: 0.7;' }
|
onmouseleave: [hover, false],
|
||||||
],
|
css: {
|
||||||
onmouseleave: [
|
cursor: selectMode ? 'pointer' : 'zoom-in'
|
||||||
patchRefStyleMap,
|
}
|
||||||
{ [photoSelectButtonRef]: 'opacity: 0;', [photoBackgroundRef]: 'opacity: 0;' }
|
|
||||||
]
|
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
vw(AttachmentImageView, doc, doc._hash()),
|
AttachmentImageView(doc, {
|
||||||
|
css: {
|
||||||
|
transform: isSelected ? 'translateZ(-50px)' : null
|
||||||
|
}
|
||||||
|
}),
|
||||||
photoSelectButton(
|
photoSelectButton(
|
||||||
{
|
{
|
||||||
_ref: photoSelectButtonRef,
|
_ref: photoSelectButtonRef,
|
||||||
|
_data: doc,
|
||||||
|
class: 'photoSelect',
|
||||||
css: {
|
css: {
|
||||||
// backgroundColor: isSelected ? 'white' : 'transparent',
|
backgroundColor: isSelected ? 'white' : 'transparent',
|
||||||
// opacity: isSelected ? 1 : selectMode || _imageHover ? 0.7 : 0,
|
opacity: isSelected || hoverSelectButton() ? 1 : selectMode || hover() ? 0.7 : 0
|
||||||
},
|
},
|
||||||
onmouseenter: [patchNodeStyle, 'opacity: 1;'],
|
onmouseenter: [hoverSelectButton, true],
|
||||||
onmouseleave: [patchNodeStyle, 'opacity: 0.7;']
|
onmouseleave: [hoverSelectButton, false]
|
||||||
},
|
},
|
||||||
[
|
[
|
||||||
Icon({
|
Icon({
|
||||||
name: 'check_circle',
|
name: selectMode && !isSelected ? 'circle_o' : 'check_circle',
|
||||||
size: 0.75,
|
size: 0.75,
|
||||||
fill: '#fff' // isSelected ? '#00C800' : '#fff'
|
fill: isSelected ? '#00C800' : '#fff'
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
photoBackdrop({
|
photoBackdrop({
|
||||||
_ref: photoBackgroundRef,
|
_ref: photoBackgroundRef,
|
||||||
css: {
|
css: {
|
||||||
// transform: isSelected ? 'translateZ(-50px)' : null,
|
transform: isSelected ? 'translateZ(-50px)' : null,
|
||||||
// opacity: selectMode || _imageHover ? 0.7 : 0,
|
opacity: selectMode || hover() ? 0.7 : 0
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
|
||||||
const IMAGE_MARGIN = 2;
|
|
||||||
|
|
||||||
const CSS_FULL_SIZE = {
|
|
||||||
width: '100%',
|
|
||||||
height: '100%'
|
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
const photoContainer = styled({
|
const photoContainer = styled({
|
||||||
position: 'relative',
|
position: 'relative',
|
||||||
@ -70,21 +81,18 @@ const photoContainer = styled({
|
|||||||
cursor: 'zoom-in'
|
cursor: 'zoom-in'
|
||||||
});
|
});
|
||||||
|
|
||||||
const image = styled('img', CSS_FULL_SIZE, {
|
const image = styled('img', CSS_FULL_SIZE, DEFAULT_TRANSITION, {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top: 0,
|
top: 0,
|
||||||
left: 0,
|
left: 0
|
||||||
transition: 'transform .135s cubic-bezier(0.0,0.0,0.2,1)'
|
|
||||||
});
|
});
|
||||||
|
|
||||||
const photoSelectButton = styled({
|
const photoSelectButton = styled(DEFAULT_TRANSITION, {
|
||||||
position: 'absolute',
|
position: 'absolute',
|
||||||
top: '4%',
|
top: '4%',
|
||||||
left: '4%',
|
left: '4%',
|
||||||
zIndex: 2,
|
zIndex: 2,
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
transition:
|
|
||||||
'transform .135s cubic-bezier(0.0,0.0,0.2,1), opacity .135s cubic-bezier(0.0,0.0,0.2,1)',
|
|
||||||
borderRadius: '50%',
|
borderRadius: '50%',
|
||||||
padding: '2px',
|
padding: '2px',
|
||||||
backgroundColor: 'transparent',
|
backgroundColor: 'transparent',
|
||||||
@ -92,11 +100,10 @@ const photoSelectButton = styled({
|
|||||||
cursor: 'pointer'
|
cursor: 'pointer'
|
||||||
});
|
});
|
||||||
|
|
||||||
const photoBackdrop = styled(CSS_FULL_SIZE, {
|
const photoBackdrop = styled(CSS_FULL_SIZE, DEFAULT_TRANSITION, {
|
||||||
|
position: 'absolute', // Unnecessary but helps with a rendering bug in Chrome. https://gitlab.com/explorigin/gallery/issues/1
|
||||||
top: '0px',
|
top: '0px',
|
||||||
left: '0px',
|
left: '0px',
|
||||||
zIndex: 1,
|
zIndex: 1,
|
||||||
transition:
|
|
||||||
'transform .135s cubic-bezier(0.0,0.0,0.2,1), opacity .135s cubic-bezier(0.0,0.0,0.2,1)',
|
|
||||||
backgroundImage: 'linear-gradient(to bottom,rgba(0,0,0,0.26),transparent 56px,transparent)'
|
backgroundImage: 'linear-gradient(to bottom,rgba(0,0,0,0.26),transparent 56px,transparent)'
|
||||||
});
|
});
|
||||||
|
|||||||
@ -5,13 +5,26 @@ import {
|
|||||||
patchNodeStyle
|
patchNodeStyle
|
||||||
} from '../../utils/domvm.js';
|
} from '../../utils/domvm.js';
|
||||||
import { injectStyle, styled } from '../../services/style.js';
|
import { injectStyle, styled } from '../../services/style.js';
|
||||||
|
import { DEFAULT_TRANSITION } from '../styles.js';
|
||||||
import { Icon } from './icon.js';
|
import { Icon } from './icon.js';
|
||||||
import { AlbumPhotoTemplate } from './albumPhotoTemplate.js';
|
import { AlbumPhotoTemplate } from './albumPhotoTemplate.js';
|
||||||
|
|
||||||
export function AlbumTemplate(params) {
|
export function AlbumTemplate(params) {
|
||||||
const { id, title, photos } = params;
|
const { id, title, photos, selectedIds, mode } = params;
|
||||||
const albumSelectButtonRef = `albSel${id}`;
|
const albumSelectButtonRef = `albSel${id}`;
|
||||||
|
const selectMode = mode === 'select';
|
||||||
|
|
||||||
|
function photoMap(doc) {
|
||||||
|
return vw(
|
||||||
|
AlbumPhotoTemplate,
|
||||||
|
{
|
||||||
|
doc,
|
||||||
|
isSelected: selectedIds.has(doc._id),
|
||||||
|
selectMode
|
||||||
|
},
|
||||||
|
doc._hash()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return Album(
|
return Album(
|
||||||
{
|
{
|
||||||
@ -25,12 +38,16 @@ export function AlbumTemplate(params) {
|
|||||||
{
|
{
|
||||||
_ref: albumSelectButtonRef,
|
_ref: albumSelectButtonRef,
|
||||||
onmouseenter: [patchNodeStyle, 'opacity: 1;'],
|
onmouseenter: [patchNodeStyle, 'opacity: 1;'],
|
||||||
onmouseleave: [patchNodeStyle, 'opacity: 0.7;']
|
onmouseleave: [patchNodeStyle, 'opacity: 0.7;'],
|
||||||
|
css: {
|
||||||
|
opacity: selectMode ? 0.7 : 0
|
||||||
|
},
|
||||||
|
class: 'albumSelectButton'
|
||||||
},
|
},
|
||||||
[Icon({ name: 'check_circle', size: 0.25 })]
|
[Icon({ name: 'check_circle', size: 0.25 })]
|
||||||
)
|
)
|
||||||
]),
|
]),
|
||||||
albumContent(photos.map(AlbumPhotoTemplate))
|
albumContent(photos.map(photoMap))
|
||||||
]
|
]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -50,10 +67,8 @@ const albumContent = styled({
|
|||||||
userSelect: 'none'
|
userSelect: 'none'
|
||||||
});
|
});
|
||||||
|
|
||||||
const albumSelectButton = styled({
|
const albumSelectButton = styled(DEFAULT_TRANSITION, {
|
||||||
paddingLeft: '0.5em',
|
paddingLeft: '0.5em',
|
||||||
cursor: 'pointer',
|
cursor: 'pointer',
|
||||||
opacity: 0, // TODO onhover 0.7
|
opacity: 0
|
||||||
transition:
|
|
||||||
'transform 0.135s cubic-bezier(0, 0, 0.2, 1), opacity 0.135s cubic-bezier(0, 0, 0.2, 1)'
|
|
||||||
});
|
});
|
||||||
|
|||||||
@ -4,55 +4,58 @@ import { defineElement as el } from '../../utils/domvm.js';
|
|||||||
import { ImageType } from '../../data/image.js';
|
import { ImageType } from '../../data/image.js';
|
||||||
import { FileType } from '../../data/file.js';
|
import { FileType } from '../../data/file.js';
|
||||||
import { pouchDocHash } from '../../utils/conversion.js';
|
import { pouchDocHash } from '../../utils/conversion.js';
|
||||||
|
import { styled } from '../../services/style.js';
|
||||||
|
import { DEFAULT_TRANSITION } from '../styles.js';
|
||||||
|
|
||||||
export function AttachmentImageView(vm, params) {
|
const srcMap = new Map();
|
||||||
const model = prop(params, pouchDocHash);
|
|
||||||
const id = computed(pouchDocHash, [model]);
|
|
||||||
const sizes = computed(d => d.sizes, [model]); // always update
|
|
||||||
|
|
||||||
const blobURL = prop('');
|
async function loadImageFromBlob(doc, evt, node, vm) {
|
||||||
const imageURL = computed((sizes, bURL) => bURL || sizes.thumbnail || sizes.full, [
|
const { sizes, _id } = doc;
|
||||||
sizes,
|
const options = ['thumbnail', 'preview', 'full'].filter(o => sizes.hasOwnProperty(o));
|
||||||
blobURL
|
|
||||||
]);
|
|
||||||
|
|
||||||
model.subscribe(() => {
|
|
||||||
if (blobURL()) {
|
|
||||||
URL.revokeObjectURL(blobURL());
|
|
||||||
blobURL('');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
async function loadImageFromBlob() {
|
|
||||||
const options = ['thumbnail', 'preview', 'full'].filter(o => sizes().hasOwnProperty(o));
|
|
||||||
|
|
||||||
for (let attempt of options) {
|
for (let attempt of options) {
|
||||||
try {
|
try {
|
||||||
const data = await FileType.getFromURL(sizes()[attempt]);
|
const data = await FileType.getFromURL(sizes[attempt]);
|
||||||
|
let src = evt.target.src;
|
||||||
if (blobURL()) {
|
if (src.startsWith('blob:')) {
|
||||||
URL.revokeObjectURL(blobURL());
|
URL.revokeObjectURL(src);
|
||||||
}
|
}
|
||||||
blobURL(URL.createObjectURL(data));
|
src = URL.createObjectURL(data);
|
||||||
return;
|
node.patch({ src });
|
||||||
|
srcMap.set(_id, src);
|
||||||
|
// node.data = attempt;
|
||||||
|
break;
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function cleanup() {
|
function cleanup(id, evt) {
|
||||||
URL.revokeObjectURL(blobURL());
|
const { src } = evt.target;
|
||||||
|
if (src.startsWith('blob:')) {
|
||||||
|
URL.revokeObjectURL(s);
|
||||||
|
srcMap.remove(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return function render() {
|
export function AttachmentImageView(doc, props) {
|
||||||
return el('img', {
|
const { sizes, _id } = doc;
|
||||||
src: imageURL,
|
const src = srcMap.get(_id) || sizes.thumbnail || sizes.preview || sizes.full;
|
||||||
onerror: loadImageFromBlob,
|
|
||||||
_key: id(),
|
return image(
|
||||||
|
Object.assign(
|
||||||
|
{
|
||||||
|
src,
|
||||||
|
onerror: [loadImageFromBlob, doc],
|
||||||
|
_key: _id,
|
||||||
_hooks: {
|
_hooks: {
|
||||||
didRemove: cleanup
|
didRemove: [cleanup, _id]
|
||||||
}
|
}
|
||||||
});
|
},
|
||||||
};
|
props || {}
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const image = styled('img', DEFAULT_TRANSITION);
|
||||||
|
|||||||
@ -8,7 +8,7 @@ export function ThumbnailTemplate(doc, remove, key) {
|
|||||||
{
|
{
|
||||||
onclick: { img: [remove, doc] }
|
onclick: { img: [remove, doc] }
|
||||||
},
|
},
|
||||||
[vw(AttachmentImageView, doc, key)]
|
[AttachmentImageView(doc)]
|
||||||
)
|
)
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|||||||
11
packages/gallery/src/interface/styles.js
Normal file
11
packages/gallery/src/interface/styles.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
export const IMAGE_MARGIN = 2;
|
||||||
|
|
||||||
|
export const CSS_FULL_SIZE = {
|
||||||
|
width: '100%',
|
||||||
|
height: '100%'
|
||||||
|
};
|
||||||
|
|
||||||
|
export const DEFAULT_TRANSITION = {
|
||||||
|
transition:
|
||||||
|
'transform 0.135s cubic-bezier(0, 0, 0.2, 1), opacity 0.135s cubic-bezier(0, 0, 0.2, 1)'
|
||||||
|
};
|
||||||
@ -16,6 +16,6 @@ export function isObject(obj) {
|
|||||||
return typeof obj === 'object' && !Array.isArray(obj);
|
return typeof obj === 'object' && !Array.isArray(obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isString(str) {
|
export function isString(obj) {
|
||||||
return typeof obj === 'string';
|
return typeof obj === 'string';
|
||||||
}
|
}
|
||||||
|
|||||||
@ -49,3 +49,13 @@ export const pick = id => doc => doc[id];
|
|||||||
|
|
||||||
export const extractID = pick('_id');
|
export const extractID = pick('_id');
|
||||||
export const extractREV = pick('_rev');
|
export const extractREV = pick('_rev');
|
||||||
|
|
||||||
|
export function hashSet(_a) {
|
||||||
|
if (_a instanceof Set) {
|
||||||
|
return Array.from(_a.keys())
|
||||||
|
.sort()
|
||||||
|
.map(k => `${(typeof k).substr(0, 1)}:${encodeURIComponent(k)}/`)
|
||||||
|
.join('?');
|
||||||
|
}
|
||||||
|
return _a;
|
||||||
|
}
|
||||||
|
|||||||
@ -1,8 +1,9 @@
|
|||||||
// export * from 'domvm/dist/dev/domvm.dev.js';
|
// export * from 'domvm/dist/dev/domvm.dev.js';
|
||||||
export * from 'domvm/dist/mini/domvm.mini.js';
|
export * from 'domvm/dist/mini/domvm.mini.js';
|
||||||
|
import { deepAssign } from './conversion.js';
|
||||||
|
|
||||||
export function subscribeToRender(vm, subscribables, subscriptions) {
|
export function subscribeToRender(vm, subscribables, subscriptions) {
|
||||||
const redraw = () => vm.redraw();
|
const redraw = (...args) => vm.redraw();
|
||||||
const subList = subscribables.map(s => s.subscribe(redraw)).concat(subscriptions);
|
const subList = subscribables.map(s => s.subscribe(redraw)).concat(subscriptions);
|
||||||
|
|
||||||
vm.config({ hooks: { willUnmount: () => subList.forEach(s => s()) } });
|
vm.config({ hooks: { willUnmount: () => subList.forEach(s => s()) } });
|
||||||
@ -12,10 +13,16 @@ export function patchRefStyle(ref, style, evt, node, vm) {
|
|||||||
vm.refs[ref].patch({ style });
|
vm.refs[ref].patch({ style });
|
||||||
}
|
}
|
||||||
|
|
||||||
export function patchRefStyleMap(refStylemap, ...args) {
|
export function patchRefStyleMap(refStyleMap, ...args) {
|
||||||
Object.entries(refStylemap).forEach(([r, s]) => patchRefStyle(r, s, ...args));
|
Object.entries(refStyleMap).forEach(([r, s]) => patchRefStyle(r, s, ...args));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function patchNodeStyle(style, evt, node) {
|
export function patchNodeStyle(style, evt, node) {
|
||||||
node.patch({ style });
|
node.patch({ style });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function changeElementStateMap(refStateMap, evt, node, vm) {
|
||||||
|
Object.entries(refStateMap).forEach(([r, state]) => {
|
||||||
|
deepAssign(vm.refs[ref]._data, state);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user