chore: merge blocksuite source code (#9213)

This commit is contained in:
Mirone
2024-12-20 15:38:06 +08:00
committed by GitHub
parent 2c9ef916f4
commit 30200ff86d
2031 changed files with 238888 additions and 229 deletions
@@ -0,0 +1,100 @@
import { popupTargetFromElement } from '@blocksuite/affine-components/context-menu';
import { computed, signal } from '@preact/signals-core';
import { html } from 'lit/static-html.js';
import { popTagSelect } from '../../core/component/tags/multi-tag-select.js';
import type { SelectTag } from '../../core/index.js';
import { BaseCellRenderer } from '../../core/property/index.js';
import { createFromBaseCellRenderer } from '../../core/property/renderer.js';
import { createIcon } from '../../core/utils/uni-icon.js';
import type { SelectPropertyData } from '../select/define.js';
import { multiSelectPropertyModelConfig } from './define.js';
export class MultiSelectCell extends BaseCellRenderer<
string[],
SelectPropertyData
> {
override render() {
return html`
<affine-multi-tag-view
.value="${Array.isArray(this.value) ? this.value : []}"
.options="${this.property.data$.value.options}"
></affine-multi-tag-view>
`;
}
}
export class MultiSelectCellEditing extends BaseCellRenderer<
string[],
SelectPropertyData
> {
private popTagSelect = () => {
const value = signal(this._value);
this._disposables.add({
dispose: popTagSelect(
popupTargetFromElement(
this.querySelector('affine-multi-tag-view') ?? this
),
{
name: this.cell.property.name$.value,
options: this.options$,
onOptionsChange: this._onOptionsChange,
value: value,
onChange: v => {
this._onChange(v);
value.value = v;
},
onComplete: this._editComplete,
minWidth: 400,
}
),
});
};
_editComplete = () => {
this.selectCurrentCell(false);
};
_onChange = (ids: string[]) => {
this.onChange(ids);
};
_onOptionsChange = (options: SelectTag[]) => {
this.property.dataUpdate(data => {
return {
...data,
options,
};
});
};
options$ = computed(() => {
return this.property.data$.value.options;
});
get _value() {
return this.value ?? [];
}
override firstUpdated() {
this.popTagSelect();
}
override render() {
return html`
<affine-multi-tag-view
.value="${this._value}"
.options="${this.options$.value}"
></affine-multi-tag-view>
`;
}
}
export const multiSelectPropertyConfig =
multiSelectPropertyModelConfig.createPropertyMeta({
icon: createIcon('MultiSelectIcon'),
cellRenderer: {
view: createFromBaseCellRenderer(MultiSelectCell),
edit: createFromBaseCellRenderer(MultiSelectCellEditing),
},
});
@@ -0,0 +1,69 @@
import { nanoid } from '@blocksuite/store';
import { getTagColor } from '../../core/component/tags/colors.js';
import { type SelectTag, t } from '../../core/index.js';
import { propertyType } from '../../core/property/property-config.js';
import type { SelectPropertyData } from '../select/define.js';
export const multiSelectPropertyType = propertyType('multi-select');
export const multiSelectPropertyModelConfig =
multiSelectPropertyType.modelConfig<string[], SelectPropertyData>({
name: 'Multi-select',
type: ({ data }) => t.array.instance(t.tag.instance(data.options)),
defaultData: () => ({
options: [],
}),
addGroup: ({ text, oldData }) => {
return {
options: [
...(oldData.options ?? []),
{
id: nanoid(),
value: text,
color: getTagColor(),
},
],
};
},
formatValue: ({ value }) => {
if (Array.isArray(value)) {
return value.filter(v => v != null);
}
return [];
},
cellToString: ({ value, data }) =>
value?.map(id => data.options.find(v => v.id === id)?.value).join(','),
cellFromString: ({ value: oldValue, data }) => {
const optionMap = Object.fromEntries(data.options.map(v => [v.value, v]));
const optionNames = oldValue
.split(',')
.map(v => v.trim())
.filter(v => v);
const value: string[] = [];
optionNames.forEach(name => {
if (!optionMap[name]) {
const newOption: SelectTag = {
id: nanoid(),
value: name,
color: getTagColor(),
};
data.options.push(newOption);
value.push(newOption.id);
} else {
value.push(optionMap[name].id);
}
});
return {
value,
data: data,
};
},
cellToJson: ({ value }) => value ?? null,
cellFromJson: ({ value }) =>
Array.isArray(value) && value.every(v => typeof v === 'string')
? value
: undefined,
isEmpty: ({ value }) => value == null || value.length === 0,
});