refactor(editor): add schema for value of database block properties (#10749)
This commit is contained in:
@@ -36,7 +36,7 @@ todoMeta.addProperty({
|
|||||||
metaConfig: propertyPresets.checkboxPropertyConfig,
|
metaConfig: propertyPresets.checkboxPropertyConfig,
|
||||||
get: block => block.checked,
|
get: block => block.checked,
|
||||||
set: (block, value) => {
|
set: (block, value) => {
|
||||||
block.checked = value;
|
block.checked = value ?? false;
|
||||||
},
|
},
|
||||||
updated: (block, callback) => {
|
updated: (block, callback) => {
|
||||||
return block.propsUpdated.on(({ key }) => {
|
return block.propsUpdated.on(({ key }) => {
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ export const queryBlockColumns = [
|
|||||||
propertyPresets.multiSelectPropertyConfig,
|
propertyPresets.multiSelectPropertyConfig,
|
||||||
propertyPresets.checkboxPropertyConfig,
|
propertyPresets.checkboxPropertyConfig,
|
||||||
];
|
];
|
||||||
export const queryBlockHiddenColumns = [richTextColumnConfig];
|
export const queryBlockHiddenColumns: PropertyMetaConfig<string, any, any>[] = [
|
||||||
|
richTextColumnConfig,
|
||||||
|
];
|
||||||
const queryBlockAllColumns = [...queryBlockColumns, ...queryBlockHiddenColumns];
|
const queryBlockAllColumns = [...queryBlockColumns, ...queryBlockHiddenColumns];
|
||||||
export const queryBlockAllColumnMap = Object.fromEntries(
|
export const queryBlockAllColumnMap = Object.fromEntries(
|
||||||
queryBlockAllColumns.map(v => [v.type, v as PropertyMetaConfig])
|
queryBlockAllColumns.map(v => [v.type, v as PropertyMetaConfig])
|
||||||
|
|||||||
@@ -8,6 +8,5 @@ export * from './detail-panel/block-renderer';
|
|||||||
export * from './detail-panel/note-renderer';
|
export * from './detail-panel/note-renderer';
|
||||||
export * from './properties';
|
export * from './properties';
|
||||||
export * from './properties/rich-text/cell-renderer';
|
export * from './properties/rich-text/cell-renderer';
|
||||||
export * from './properties/utils';
|
|
||||||
export * from './selection.js';
|
export * from './selection.js';
|
||||||
export * from './utils/block-utils';
|
export * from './utils/block-utils';
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
import { propertyType, t } from '@blocksuite/data-view';
|
import { propertyType, t } from '@blocksuite/data-view';
|
||||||
|
import zod from 'zod';
|
||||||
export const linkColumnType = propertyType('link');
|
export const linkColumnType = propertyType('link');
|
||||||
export const linkPropertyModelConfig = linkColumnType.modelConfig<string>({
|
export const linkPropertyModelConfig = linkColumnType.modelConfig({
|
||||||
name: 'Link',
|
name: 'Link',
|
||||||
|
valueSchema: zod.string().optional(),
|
||||||
type: () => t.string.instance(),
|
type: () => t.string.instance(),
|
||||||
defaultData: () => ({}),
|
defaultData: () => ({}),
|
||||||
cellToString: ({ value }) => value?.toString() ?? '',
|
cellToString: ({ value }) => value?.toString() ?? '',
|
||||||
|
|||||||
@@ -2,56 +2,68 @@ import type { AffineTextAttributes } from '@blocksuite/affine-shared/types';
|
|||||||
import { propertyType, t } from '@blocksuite/data-view';
|
import { propertyType, t } from '@blocksuite/data-view';
|
||||||
import type { DeltaInsert } from '@blocksuite/inline';
|
import type { DeltaInsert } from '@blocksuite/inline';
|
||||||
import { Text } from '@blocksuite/store';
|
import { Text } from '@blocksuite/store';
|
||||||
|
import * as Y from 'yjs';
|
||||||
|
import zod from 'zod';
|
||||||
|
|
||||||
import { HostContextKey } from '../../context/host-context.js';
|
import { HostContextKey } from '../../context/host-context.js';
|
||||||
import { isLinkedDoc } from '../../utils/title-doc.js';
|
import { isLinkedDoc } from '../../utils/title-doc.js';
|
||||||
import { type RichTextCellType, toYText } from '../utils.js';
|
|
||||||
|
|
||||||
export const richTextColumnType = propertyType('rich-text');
|
export const richTextColumnType = propertyType('rich-text');
|
||||||
|
export type RichTextCellType = Text | Text['yText'];
|
||||||
|
export const toYText = (text?: RichTextCellType): undefined | Text['yText'] => {
|
||||||
|
if (text instanceof Text) {
|
||||||
|
return text.yText;
|
||||||
|
}
|
||||||
|
return text;
|
||||||
|
};
|
||||||
|
|
||||||
export const richTextPropertyModelConfig =
|
export const richTextPropertyModelConfig = richTextColumnType.modelConfig({
|
||||||
richTextColumnType.modelConfig<RichTextCellType>({
|
name: 'Text',
|
||||||
name: 'Text',
|
valueSchema: zod
|
||||||
type: () => t.richText.instance(),
|
.custom<RichTextCellType>(
|
||||||
defaultData: () => ({}),
|
data => data instanceof Text || data instanceof Y.Text
|
||||||
cellToString: ({ value }) => value?.toString() ?? '',
|
)
|
||||||
cellFromString: ({ value }) => {
|
.optional(),
|
||||||
return {
|
type: () => t.richText.instance(),
|
||||||
value: new Text(value),
|
defaultData: () => ({}),
|
||||||
};
|
cellToString: ({ value }) => value?.toString() ?? '',
|
||||||
},
|
cellFromString: ({ value }) => {
|
||||||
cellToJson: ({ value, dataSource }) => {
|
return {
|
||||||
if (!value) return null;
|
value: new Text(value),
|
||||||
const host = dataSource.contextGet(HostContextKey);
|
};
|
||||||
if (host) {
|
},
|
||||||
const collection = host.std.workspace;
|
cellToJson: ({ value, dataSource }) => {
|
||||||
const yText = toYText(value);
|
if (!value) return null;
|
||||||
const deltas = yText.toDelta();
|
const host = dataSource.contextGet(HostContextKey);
|
||||||
const text = deltas
|
if (host) {
|
||||||
.map((delta: DeltaInsert<AffineTextAttributes>) => {
|
const collection = host.std.workspace;
|
||||||
if (isLinkedDoc(delta)) {
|
|
||||||
const linkedDocId = delta.attributes?.reference?.pageId as string;
|
|
||||||
return collection.getDoc(linkedDocId)?.meta?.title;
|
|
||||||
}
|
|
||||||
return delta.insert;
|
|
||||||
})
|
|
||||||
.join('');
|
|
||||||
return text;
|
|
||||||
}
|
|
||||||
return value?.toString() ?? null;
|
|
||||||
},
|
|
||||||
cellFromJson: ({ value }) =>
|
|
||||||
typeof value !== 'string' ? undefined : new Text(value),
|
|
||||||
onUpdate: ({ value, callback }) => {
|
|
||||||
const yText = toYText(value);
|
const yText = toYText(value);
|
||||||
yText.observe(callback);
|
const deltas = yText?.toDelta();
|
||||||
callback();
|
const text = deltas
|
||||||
return {
|
.map((delta: DeltaInsert<AffineTextAttributes>) => {
|
||||||
dispose: () => {
|
if (isLinkedDoc(delta)) {
|
||||||
yText.unobserve(callback);
|
const linkedDocId = delta.attributes?.reference?.pageId as string;
|
||||||
},
|
return collection.getDoc(linkedDocId)?.meta?.title;
|
||||||
};
|
}
|
||||||
},
|
return delta.insert;
|
||||||
isEmpty: ({ value }) => value == null || value.length === 0,
|
})
|
||||||
values: ({ value }) => (value?.toString() ? [value.toString()] : []),
|
.join('');
|
||||||
});
|
return text;
|
||||||
|
}
|
||||||
|
return value?.toString() ?? null;
|
||||||
|
},
|
||||||
|
cellFromJson: ({ value }) =>
|
||||||
|
typeof value !== 'string' ? undefined : new Text(value),
|
||||||
|
onUpdate: ({ value, callback }) => {
|
||||||
|
const yText = toYText(value);
|
||||||
|
yText?.observe(callback);
|
||||||
|
callback();
|
||||||
|
return {
|
||||||
|
dispose: () => {
|
||||||
|
yText?.unobserve(callback);
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
isEmpty: ({ value }) => value == null || value.length === 0,
|
||||||
|
values: ({ value }) => (value?.toString() ? [value.toString()] : []),
|
||||||
|
});
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
import { propertyType, t } from '@blocksuite/data-view';
|
import { propertyType, t } from '@blocksuite/data-view';
|
||||||
import { Text } from '@blocksuite/store';
|
import { Text } from '@blocksuite/store';
|
||||||
|
import zod from 'zod';
|
||||||
|
|
||||||
import { HostContextKey } from '../../context/host-context.js';
|
import { HostContextKey } from '../../context/host-context.js';
|
||||||
import { isLinkedDoc } from '../../utils/title-doc.js';
|
import { isLinkedDoc } from '../../utils/title-doc.js';
|
||||||
|
|
||||||
export const titleColumnType = propertyType('title');
|
export const titleColumnType = propertyType('title');
|
||||||
|
|
||||||
export const titlePropertyModelConfig = titleColumnType.modelConfig<Text>({
|
export const titlePropertyModelConfig = titleColumnType.modelConfig({
|
||||||
name: 'Title',
|
name: 'Title',
|
||||||
|
valueSchema: zod.custom<Text>(data => data instanceof Text).optional(),
|
||||||
fixed: {
|
fixed: {
|
||||||
defaultData: {},
|
defaultData: {},
|
||||||
defaultShow: true,
|
defaultShow: true,
|
||||||
@@ -42,22 +44,22 @@ export const titlePropertyModelConfig = titleColumnType.modelConfig<Text>({
|
|||||||
cellFromJson: ({ value }) =>
|
cellFromJson: ({ value }) =>
|
||||||
typeof value !== 'string' ? undefined : new Text(value),
|
typeof value !== 'string' ? undefined : new Text(value),
|
||||||
onUpdate: ({ value, callback }) => {
|
onUpdate: ({ value, callback }) => {
|
||||||
value.yText.observe(callback);
|
value?.yText.observe(callback);
|
||||||
callback();
|
callback();
|
||||||
return {
|
return {
|
||||||
dispose: () => {
|
dispose: () => {
|
||||||
value.yText.unobserve(callback);
|
value?.yText.unobserve(callback);
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
valueUpdate: ({ value, newValue }) => {
|
valueUpdate: ({ value, newValue }) => {
|
||||||
const v = newValue as unknown;
|
const v = newValue as unknown;
|
||||||
if (typeof v === 'string') {
|
if (typeof v === 'string') {
|
||||||
value.replace(0, value.length, v);
|
value?.replace(0, value.length, v);
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
if (v == null) {
|
if (v == null) {
|
||||||
value.replace(0, value.length, '');
|
value?.replace(0, value.length, '');
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
return newValue;
|
return newValue;
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
import { Text } from '@blocksuite/store';
|
|
||||||
|
|
||||||
export type RichTextCellType = Text | Text['yText'];
|
|
||||||
export const toYText = (text: RichTextCellType): Text['yText'] => {
|
|
||||||
if (text instanceof Text) {
|
|
||||||
return text.yText;
|
|
||||||
}
|
|
||||||
return text;
|
|
||||||
};
|
|
||||||
@@ -197,7 +197,7 @@ export abstract class DataSourceBase implements DataSource {
|
|||||||
return computed(() => this.propertyReadonlyGet(propertyId));
|
return computed(() => this.propertyReadonlyGet(propertyId));
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract propertyTypeGet(propertyId: string): string;
|
abstract propertyTypeGet(propertyId: string): string | undefined;
|
||||||
|
|
||||||
propertyTypeGet$(propertyId: string): ReadonlySignal<string | undefined> {
|
propertyTypeGet$(propertyId: string): ReadonlySignal<string | undefined> {
|
||||||
return computed(() => this.propertyTypeGet(propertyId));
|
return computed(() => this.propertyTypeGet(propertyId));
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import type { Disposable } from '@blocksuite/global/slot';
|
import type { Disposable } from '@blocksuite/global/slot';
|
||||||
|
import type { ZodType } from 'zod';
|
||||||
|
|
||||||
import type { DataSource } from '../data-source/base.js';
|
import type { DataSource } from '../data-source/base.js';
|
||||||
import type { TypeInstance } from '../logical/type.js';
|
import type { TypeInstance } from '../logical/type.js';
|
||||||
@@ -15,6 +16,7 @@ export type PropertyConfig<
|
|||||||
Value = unknown,
|
Value = unknown,
|
||||||
> = {
|
> = {
|
||||||
name: string;
|
name: string;
|
||||||
|
valueSchema: ZodType<Value>;
|
||||||
hide?: boolean;
|
hide?: boolean;
|
||||||
fixed?: {
|
fixed?: {
|
||||||
defaultData: Data;
|
defaultData: Data;
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
import zod from 'zod';
|
||||||
|
|
||||||
import { t } from '../../core/logical/type-presets.js';
|
import { t } from '../../core/logical/type-presets.js';
|
||||||
import { propertyType } from '../../core/property/property-config.js';
|
import { propertyType } from '../../core/property/property-config.js';
|
||||||
|
|
||||||
export const checkboxPropertyType = propertyType('checkbox');
|
export const checkboxPropertyType = propertyType('checkbox');
|
||||||
|
|
||||||
const FALSE_VALUES = new Set([
|
const FALSE_VALUES = new Set([
|
||||||
@@ -18,18 +19,17 @@ const FALSE_VALUES = new Set([
|
|||||||
'关闭',
|
'关闭',
|
||||||
]);
|
]);
|
||||||
|
|
||||||
export const checkboxPropertyModelConfig =
|
export const checkboxPropertyModelConfig = checkboxPropertyType.modelConfig({
|
||||||
checkboxPropertyType.modelConfig<boolean>({
|
name: 'Checkbox',
|
||||||
name: 'Checkbox',
|
valueSchema: zod.boolean().optional(),
|
||||||
type: () => t.boolean.instance(),
|
type: () => t.boolean.instance(),
|
||||||
defaultData: () => ({}),
|
defaultData: () => ({}),
|
||||||
cellToString: ({ value }) => (value ? 'True' : 'False'),
|
cellToString: ({ value }) => (value ? 'True' : 'False'),
|
||||||
cellFromString: ({ value }) => ({
|
cellFromString: ({ value }) => ({
|
||||||
value: !FALSE_VALUES.has((value?.trim() ?? '').toLowerCase()),
|
value: !FALSE_VALUES.has((value?.trim() ?? '').toLowerCase()),
|
||||||
}),
|
}),
|
||||||
cellToJson: ({ value }) => value ?? null,
|
cellToJson: ({ value }) => value ?? null,
|
||||||
cellFromJson: ({ value }) =>
|
cellFromJson: ({ value }) => (typeof value !== 'boolean' ? undefined : value),
|
||||||
typeof value !== 'boolean' ? undefined : value,
|
isEmpty: () => false,
|
||||||
isEmpty: () => false,
|
minWidth: 34,
|
||||||
minWidth: 34,
|
});
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,15 +1,17 @@
|
|||||||
import { format } from 'date-fns/format';
|
import { format } from 'date-fns/format';
|
||||||
import { parse } from 'date-fns/parse';
|
import { parse } from 'date-fns/parse';
|
||||||
|
import zod from 'zod';
|
||||||
|
|
||||||
import { t } from '../../core/logical/type-presets.js';
|
import { t } from '../../core/logical/type-presets.js';
|
||||||
import { propertyType } from '../../core/property/property-config.js';
|
import { propertyType } from '../../core/property/property-config.js';
|
||||||
|
|
||||||
export const datePropertyType = propertyType('date');
|
export const datePropertyType = propertyType('date');
|
||||||
export const datePropertyModelConfig = datePropertyType.modelConfig<number>({
|
export const datePropertyModelConfig = datePropertyType.modelConfig({
|
||||||
name: 'Date',
|
name: 'Date',
|
||||||
type: () => t.date.instance(),
|
type: () => t.date.instance(),
|
||||||
|
valueSchema: zod.number().optional(),
|
||||||
defaultData: () => ({}),
|
defaultData: () => ({}),
|
||||||
cellToString: ({ value }) => format(value, 'yyyy-MM-dd'),
|
cellToString: ({ value }) =>
|
||||||
|
value != null ? format(value, 'yyyy-MM-dd') : '',
|
||||||
cellFromString: ({ value }) => {
|
cellFromString: ({ value }) => {
|
||||||
const date = parse(value, 'yyyy-MM-dd', new Date());
|
const date = parse(value, 'yyyy-MM-dd', new Date());
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
|
import zod from 'zod';
|
||||||
|
|
||||||
import { t } from '../../core/logical/type-presets.js';
|
import { t } from '../../core/logical/type-presets.js';
|
||||||
import { propertyType } from '../../core/property/property-config.js';
|
import { propertyType } from '../../core/property/property-config.js';
|
||||||
|
|
||||||
export const imagePropertyType = propertyType('image');
|
export const imagePropertyType = propertyType('image');
|
||||||
|
|
||||||
export const imagePropertyModelConfig = imagePropertyType.modelConfig<string>({
|
export const imagePropertyModelConfig = imagePropertyType.modelConfig({
|
||||||
name: 'image',
|
name: 'image',
|
||||||
|
valueSchema: zod.string().optional(),
|
||||||
hide: true,
|
hide: true,
|
||||||
type: () => t.image.instance(),
|
type: () => t.image.instance(),
|
||||||
defaultData: () => ({}),
|
defaultData: () => ({}),
|
||||||
|
|||||||
@@ -1,69 +1,76 @@
|
|||||||
import { nanoid } from '@blocksuite/store';
|
import { nanoid } from '@blocksuite/store';
|
||||||
|
import zod from 'zod';
|
||||||
|
|
||||||
import { getTagColor } from '../../core/component/tags/colors.js';
|
import { getTagColor } from '../../core/component/tags/colors.js';
|
||||||
import { type SelectTag, t } from '../../core/index.js';
|
import { type SelectTag, t } from '../../core/index.js';
|
||||||
import { propertyType } from '../../core/property/property-config.js';
|
import { propertyType } from '../../core/property/property-config.js';
|
||||||
import type { SelectPropertyData } from '../select/define.js';
|
import type { SelectPropertyData } from '../select/define.js';
|
||||||
|
|
||||||
export const multiSelectPropertyType = propertyType('multi-select');
|
export const multiSelectPropertyType = propertyType('multi-select');
|
||||||
export const multiSelectPropertyModelConfig =
|
export const multiSelectPropertyModelConfig =
|
||||||
multiSelectPropertyType.modelConfig<string[], SelectPropertyData>({
|
multiSelectPropertyType.modelConfig<string[] | undefined, SelectPropertyData>(
|
||||||
name: 'Multi-select',
|
{
|
||||||
type: ({ data }) => t.array.instance(t.tag.instance(data.options)),
|
name: 'Multi-select',
|
||||||
defaultData: () => ({
|
valueSchema: zod.array(zod.string()).optional(),
|
||||||
options: [],
|
type: ({ data }) => t.array.instance(t.tag.instance(data.options)),
|
||||||
}),
|
defaultData: () => ({
|
||||||
addGroup: ({ text, oldData }) => {
|
options: [],
|
||||||
return {
|
}),
|
||||||
options: [
|
addGroup: ({ text, oldData }) => {
|
||||||
...(oldData.options ?? []),
|
return {
|
||||||
{
|
options: [
|
||||||
id: nanoid(),
|
...(oldData.options ?? []),
|
||||||
value: text,
|
{
|
||||||
color: getTagColor(),
|
id: nanoid(),
|
||||||
},
|
value: text,
|
||||||
],
|
color: getTagColor(),
|
||||||
};
|
},
|
||||||
},
|
],
|
||||||
formatValue: ({ value }) => {
|
};
|
||||||
if (Array.isArray(value)) {
|
},
|
||||||
return value.filter(v => v != null);
|
formatValue: ({ value }) => {
|
||||||
}
|
if (Array.isArray(value)) {
|
||||||
return [];
|
return value.filter(v => v != null);
|
||||||
},
|
|
||||||
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 [];
|
||||||
|
},
|
||||||
|
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);
|
||||||
|
|
||||||
return {
|
const value: string[] = [];
|
||||||
value,
|
optionNames.forEach(name => {
|
||||||
data: data,
|
if (!optionMap[name]) {
|
||||||
};
|
const newOption: SelectTag = {
|
||||||
},
|
id: nanoid(),
|
||||||
cellToJson: ({ value }) => value ?? null,
|
value: name,
|
||||||
cellFromJson: ({ value }) =>
|
color: getTagColor(),
|
||||||
Array.isArray(value) && value.every(v => typeof v === 'string')
|
};
|
||||||
? value
|
data.options.push(newOption);
|
||||||
: undefined,
|
value.push(newOption.id);
|
||||||
isEmpty: ({ value }) => value == null || value.length === 0,
|
} 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,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
|
import zod from 'zod';
|
||||||
|
|
||||||
import { t } from '../../core/logical/type-presets.js';
|
import { t } from '../../core/logical/type-presets.js';
|
||||||
import { propertyType } from '../../core/property/property-config.js';
|
import { propertyType } from '../../core/property/property-config.js';
|
||||||
import type { NumberPropertyDataType } from './types.js';
|
import type { NumberPropertyDataType } from './types.js';
|
||||||
|
|
||||||
export const numberPropertyType = propertyType('number');
|
export const numberPropertyType = propertyType('number');
|
||||||
|
|
||||||
export const numberPropertyModelConfig = numberPropertyType.modelConfig<
|
export const numberPropertyModelConfig = numberPropertyType.modelConfig<
|
||||||
number,
|
number | undefined,
|
||||||
NumberPropertyDataType
|
NumberPropertyDataType
|
||||||
>({
|
>({
|
||||||
name: 'Number',
|
name: 'Number',
|
||||||
|
valueSchema: zod.number().optional(),
|
||||||
type: () => t.number.instance(),
|
type: () => t.number.instance(),
|
||||||
defaultData: () => ({ decimal: 0, format: 'number' }),
|
defaultData: () => ({ decimal: 0, format: 'number' }),
|
||||||
cellToString: ({ value }) => value?.toString() ?? '',
|
cellToString: ({ value }) => value?.toString() ?? '',
|
||||||
|
|||||||
@@ -1,24 +1,25 @@
|
|||||||
|
import zod from 'zod';
|
||||||
|
|
||||||
import { t } from '../../core/logical/type-presets.js';
|
import { t } from '../../core/logical/type-presets.js';
|
||||||
import { propertyType } from '../../core/property/property-config.js';
|
import { propertyType } from '../../core/property/property-config.js';
|
||||||
|
|
||||||
export const progressPropertyType = propertyType('progress');
|
export const progressPropertyType = propertyType('progress');
|
||||||
|
|
||||||
export const progressPropertyModelConfig =
|
export const progressPropertyModelConfig = progressPropertyType.modelConfig({
|
||||||
progressPropertyType.modelConfig<number>({
|
name: 'Progress',
|
||||||
name: 'Progress',
|
valueSchema: zod.number().optional(),
|
||||||
type: () => t.number.instance(),
|
type: () => t.number.instance(),
|
||||||
defaultData: () => ({}),
|
defaultData: () => ({}),
|
||||||
cellToString: ({ value }) => value?.toString() ?? '',
|
cellToString: ({ value }) => value?.toString() ?? '',
|
||||||
cellFromString: ({ value }) => {
|
cellFromString: ({ value }) => {
|
||||||
const num = value ? Number(value) : NaN;
|
const num = value ? Number(value) : NaN;
|
||||||
return {
|
return {
|
||||||
value: isNaN(num) ? null : num,
|
value: isNaN(num) ? null : num,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
cellToJson: ({ value }) => value ?? null,
|
cellToJson: ({ value }) => value ?? null,
|
||||||
cellFromJson: ({ value }) => {
|
cellFromJson: ({ value }) => {
|
||||||
if (typeof value !== 'number') return undefined;
|
if (typeof value !== 'number') return undefined;
|
||||||
return value;
|
return value;
|
||||||
},
|
},
|
||||||
isEmpty: () => false,
|
isEmpty: () => false,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,19 +1,20 @@
|
|||||||
import { nanoid } from '@blocksuite/store';
|
import { nanoid } from '@blocksuite/store';
|
||||||
|
import zod from 'zod';
|
||||||
|
|
||||||
import { getTagColor } from '../../core/component/tags/colors.js';
|
import { getTagColor } from '../../core/component/tags/colors.js';
|
||||||
import { type SelectTag, t } from '../../core/index.js';
|
import { type SelectTag, t } from '../../core/index.js';
|
||||||
import { propertyType } from '../../core/property/property-config.js';
|
import { propertyType } from '../../core/property/property-config.js';
|
||||||
|
|
||||||
export const selectPropertyType = propertyType('select');
|
export const selectPropertyType = propertyType('select');
|
||||||
|
|
||||||
export type SelectPropertyData = {
|
export type SelectPropertyData = {
|
||||||
options: SelectTag[];
|
options: SelectTag[];
|
||||||
};
|
};
|
||||||
export const selectPropertyModelConfig = selectPropertyType.modelConfig<
|
export const selectPropertyModelConfig = selectPropertyType.modelConfig<
|
||||||
string,
|
string | undefined,
|
||||||
SelectPropertyData
|
SelectPropertyData
|
||||||
>({
|
>({
|
||||||
name: 'Select',
|
name: 'Select',
|
||||||
|
valueSchema: zod.string().optional(),
|
||||||
type: ({ data }) => t.tag.instance(data.options),
|
type: ({ data }) => t.tag.instance(data.options),
|
||||||
defaultData: () => ({
|
defaultData: () => ({
|
||||||
options: [],
|
options: [],
|
||||||
|
|||||||
@@ -1,10 +1,12 @@
|
|||||||
|
import zod from 'zod';
|
||||||
|
|
||||||
import { t } from '../../core/index.js';
|
import { t } from '../../core/index.js';
|
||||||
import { propertyType } from '../../core/property/property-config.js';
|
import { propertyType } from '../../core/property/property-config.js';
|
||||||
|
|
||||||
export const textPropertyType = propertyType('text');
|
export const textPropertyType = propertyType('text');
|
||||||
|
|
||||||
export const textPropertyModelConfig = textPropertyType.modelConfig<string>({
|
export const textPropertyModelConfig = textPropertyType.modelConfig({
|
||||||
name: 'Plain-Text',
|
name: 'Plain-Text',
|
||||||
|
valueSchema: zod.string().optional(),
|
||||||
type: () => t.string.instance(),
|
type: () => t.string.instance(),
|
||||||
defaultData: () => ({}),
|
defaultData: () => ({}),
|
||||||
cellToString: ({ value }) => value ?? '',
|
cellToString: ({ value }) => value ?? '',
|
||||||
|
|||||||
Reference in New Issue
Block a user