mirror of
https://github.com/dream-num/univer.git
synced 2026-09-01 15:29:43 +08:00
style(plugin): fix ts error in base-numfmt-engine/sheets-plugin-filter/sheets-plugin-numfmt (#188)
* style(base-numfmt-engine): fix ts error * style(sheets-plugin-filter): fix ts error * style(sheets-plugin-numfmt): fix ts error
This commit is contained in:
@@ -67,20 +67,21 @@ export function formatNumber(value: string | number, parts: PartType[], opts: Op
|
||||
if (value == null) {
|
||||
return '';
|
||||
}
|
||||
if (typeof value !== 'number') {
|
||||
// FIXME Both runPart and isFinite require Number type
|
||||
if (typeof value === 'number') {
|
||||
return runPart(value, text_part, opts, l10n);
|
||||
}
|
||||
// guard against non-finite numbers:
|
||||
if (!isFinite(value)) {
|
||||
if (!isFinite(Number(value))) {
|
||||
const loc: any = l10n || defaultLocale;
|
||||
if (isNaN(value)) {
|
||||
if (isNaN(Number(value))) {
|
||||
return loc.nan;
|
||||
}
|
||||
return (value < 0 ? loc.negative : '') + loc.infinity;
|
||||
return (Number(value) < 0 ? loc.negative : '') + loc.infinity;
|
||||
}
|
||||
// find and run the pattern part that applies to this number
|
||||
const part = getPart(value, parts);
|
||||
return part ? runPart(value, part, opts, l10n) : '';
|
||||
const part = getPart(Number(value), parts);
|
||||
return part ? runPart(Number(value), part, opts, l10n) : '';
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -9,7 +9,7 @@ const zero = {
|
||||
};
|
||||
|
||||
// returns the count of digits (including - and .) need to represent the number
|
||||
export function numdec(value, incl_sign = true) {
|
||||
export function numdec(value: number, incl_sign = true) {
|
||||
const v = Math.abs(value);
|
||||
|
||||
// shortcut zero
|
||||
|
||||
@@ -44,12 +44,13 @@ export function options(opts: OptionsData = {}): OptionsData {
|
||||
if (opts) {
|
||||
for (const key in opts) {
|
||||
if (key in defaultOptions) {
|
||||
const value = opts[key];
|
||||
const k = key as keyof OptionsData;
|
||||
const value = opts[k];
|
||||
if (value == null) {
|
||||
// set back to default
|
||||
globalOptions[key] = defaultOptions[key];
|
||||
globalOptions[k] = defaultOptions[k] as undefined;
|
||||
} else {
|
||||
globalOptions[key] = value;
|
||||
globalOptions[k] = value as any;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,8 +36,8 @@ export function parsePattern(pattern: string): PatternType {
|
||||
l10n_override = resolveLocale(part.locale);
|
||||
}
|
||||
partitions.push(part);
|
||||
more = p.charAt(part.pattern.length) === ';' ? 1 : 0;
|
||||
p = p.slice(part.pattern.length + more);
|
||||
more = part.pattern && p.charAt((part.pattern || '').length) === ';' ? 1 : 0;
|
||||
p = p.slice((part.pattern || '').length + more);
|
||||
i++;
|
||||
} while (more && i < 4 && conditions < 3);
|
||||
|
||||
@@ -66,15 +66,17 @@ export function parsePattern(pattern: string): PatternType {
|
||||
}
|
||||
// missing negative
|
||||
if (partitions.length < 2) {
|
||||
const part = parsePart(partitions[0].pattern);
|
||||
const part = parsePart(partitions[0].pattern || '');
|
||||
// the volatile minus only happens if there is a single pattern
|
||||
part.tokens.unshift({ type: 'minus', volatile: true });
|
||||
if (part.tokens) {
|
||||
part.tokens.unshift({ type: 'minus', volatile: true });
|
||||
}
|
||||
part.generated = true;
|
||||
partitions.push(part);
|
||||
}
|
||||
// missing zero
|
||||
if (partitions.length < 3) {
|
||||
const part = parsePart(partitions[0].pattern);
|
||||
const part = parsePart(partitions[0].pattern || '');
|
||||
part.generated = true;
|
||||
partitions.push(part);
|
||||
}
|
||||
@@ -91,26 +93,26 @@ export function parsePattern(pattern: string): PatternType {
|
||||
|
||||
partitions[0].condition = ['>', 0];
|
||||
partitions[1].condition = ['<', 0];
|
||||
partitions[2].condition = null;
|
||||
partitions[2].condition = undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
pattern,
|
||||
partitions,
|
||||
locale: l10n_override,
|
||||
locale: l10n_override as string | undefined,
|
||||
};
|
||||
}
|
||||
|
||||
export function parseCatch(pattern: string): PatternType {
|
||||
try {
|
||||
return parsePattern(pattern);
|
||||
} catch (err) {
|
||||
} catch (err: unknown) {
|
||||
const errPart = { tokens: [{ type: 'error' }] };
|
||||
return {
|
||||
pattern,
|
||||
locale: null,
|
||||
locale: undefined,
|
||||
partitions: [errPart, errPart, errPart, errPart],
|
||||
error: err.message,
|
||||
error: (err as Error).message,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Excel uses symmetric arithmetic rounding
|
||||
export function round(value: number, places: number = 0) {
|
||||
export function round(value: number, places: number = 0): number {
|
||||
if (typeof value !== 'number') {
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import { toYMD } from './toYMD';
|
||||
|
||||
const floor = Math.floor;
|
||||
const DAYSIZE = 86400;
|
||||
|
||||
export function dateToSerial(value, opts) {
|
||||
export function dateToSerial(value: Date | any[], opts?: { ignoreTimezone?: boolean }): number | any[] | Date {
|
||||
let ts = null;
|
||||
if (Array.isArray(value)) {
|
||||
const [y, m, d, hh, mm, ss] = value;
|
||||
@@ -24,24 +21,24 @@ export function dateToSerial(value, opts) {
|
||||
return value;
|
||||
}
|
||||
|
||||
export function dateFromSerial(value, opts) {
|
||||
export function dateFromSerial(value: number, opts?: { leap1900?: boolean; nativeDate?: boolean }): number[] | Date {
|
||||
let date = value | 0;
|
||||
const t = DAYSIZE * (value - date);
|
||||
let time = floor(t); // in seconds
|
||||
const t = 86400 * (value - date);
|
||||
let time = Math.floor(t); // in seconds
|
||||
// date "epsilon" correction
|
||||
if (t - time > 0.9999) {
|
||||
time += 1;
|
||||
if (time === DAYSIZE) {
|
||||
if (time === 86400) {
|
||||
time = 0;
|
||||
date += 1;
|
||||
}
|
||||
}
|
||||
// serial date/time to gregorian calendar
|
||||
const x = time < 0 ? DAYSIZE + time : time;
|
||||
const x = time < 0 ? 86400 + time : time;
|
||||
const [y, m, d] = toYMD(value, 0, opts && opts.leap1900);
|
||||
const hh = floor(x / 60 / 60) % 60;
|
||||
const mm = floor(x / 60) % 60;
|
||||
const ss = floor(x) % 60;
|
||||
const hh = Math.floor(x / 3600) % 24;
|
||||
const mm = Math.floor(x / 60) % 60;
|
||||
const ss = Math.floor(x) % 60;
|
||||
// return it as a native date object
|
||||
if (opts && opts.nativeDate) {
|
||||
const dt = new Date(0);
|
||||
|
||||
@@ -3,7 +3,7 @@ import { EPOCH_1317, EPOCH_1904 } from './constants';
|
||||
const floor = Math.floor;
|
||||
|
||||
// https://www.codeproject.com/Articles/2750/Excel-Serial-Date-to-Day-Month-Year-and-Vice-Versa
|
||||
export function toYMD_1900(ord, leap1900 = true) {
|
||||
export function toYMD_1900(ord: number, leap1900 = true) {
|
||||
if (leap1900 && ord >= 0) {
|
||||
if (ord === 0) {
|
||||
return [1900, 1, 0];
|
||||
@@ -16,26 +16,26 @@ export function toYMD_1900(ord, leap1900 = true) {
|
||||
}
|
||||
}
|
||||
let l = ord + 68569 + 2415019;
|
||||
const n = floor((4 * l) / 146097);
|
||||
l -= floor((146097 * n + 3) / 4);
|
||||
const i = floor((4000 * (l + 1)) / 1461001);
|
||||
l = l - floor((1461 * i) / 4) + 31;
|
||||
const j = floor((80 * l) / 2447);
|
||||
const nDay = l - floor((2447 * j) / 80);
|
||||
l = floor(j / 11);
|
||||
const n = Math.floor((4 * l) / 146097);
|
||||
l -= Math.floor((146097 * n + 3) / 4);
|
||||
const i = Math.floor((4000 * (l + 1)) / 1461001);
|
||||
l = l - Math.floor((1461 * i) / 4) + 31;
|
||||
const j = Math.floor((80 * l) / 2447);
|
||||
const nDay = l - Math.floor((2447 * j) / 80);
|
||||
l = Math.floor(j / 11);
|
||||
const nMonth = j + 2 - 12 * l;
|
||||
const nYear = 100 * (n - 49) + i + l;
|
||||
return [nYear | 0, nMonth | 0, nDay | 0];
|
||||
}
|
||||
|
||||
export function toYMD_1904(ord) {
|
||||
export function toYMD_1904(ord: number) {
|
||||
return toYMD_1900(ord + 1462);
|
||||
}
|
||||
|
||||
// https://web.archive.org/web/20080209173858/https://www.microsoft.com/globaldev/DrIntl/columns/002/default.mspx
|
||||
// > [algorithm] is used in many Microsoft products, including all operating systems that
|
||||
// > support Arabic locales, Microsoft Office, COM, Visual Basics, VBA, and SQL Server 2000.
|
||||
export function toYMD_1317(ord) {
|
||||
export function toYMD_1317(ord: number) {
|
||||
if (ord === 60) {
|
||||
throw new Error('#VALUE!');
|
||||
}
|
||||
@@ -48,19 +48,19 @@ export function toYMD_1317(ord) {
|
||||
const y = 10631 / 30;
|
||||
const shift1 = 8.01 / 60;
|
||||
let z = ord + 466935;
|
||||
const cyc = floor(z / 10631);
|
||||
const cyc = Math.floor(z / 10631);
|
||||
z -= 10631 * cyc;
|
||||
const j = floor((z - shift1) / y);
|
||||
z -= floor(j * y + shift1);
|
||||
const m = floor((z + 28.5001) / 29.5);
|
||||
const j = Math.floor((z - shift1) / y);
|
||||
z -= Math.floor(j * y + shift1);
|
||||
const m = Math.floor((z + 28.5001) / 29.5);
|
||||
if (m === 13) {
|
||||
return [30 * cyc + j, 12, 30];
|
||||
}
|
||||
return [30 * cyc + j, m, z - floor(29.5001 * m - 29)];
|
||||
return [30 * cyc + j, m, z - Math.floor(29.5001 * m - 29)];
|
||||
}
|
||||
|
||||
export function toYMD(ord, system = 0, leap1900 = true) {
|
||||
const int = floor(ord);
|
||||
export function toYMD(ord: number, system = 0, leap1900 = true) {
|
||||
const int = Math.floor(ord);
|
||||
if (system === EPOCH_1317) {
|
||||
return toYMD_1317(int);
|
||||
}
|
||||
|
||||
@@ -1,16 +1,32 @@
|
||||
import { codeToLocale } from './core/codeToLocale';
|
||||
import { dec2frac } from './core/dec2frac';
|
||||
import { color, formatNumber, isDate, isPercent, isText } from './core/formatNumber';
|
||||
import { addLocale, getLocale, parseLocale } from './core/locale';
|
||||
import { addLocale, getLocale, LocaleData, parseLocale } from './core/locale';
|
||||
import { options, OptionsData } from './core/options';
|
||||
import { PartType } from './core/parsePart';
|
||||
import { parseCatch, parsePattern, PatternType } from './core/parsePattern';
|
||||
import { parseBool, parseDate, parseNumber, parseTime, parseValue } from './core/parseValue';
|
||||
import { round } from './core/round';
|
||||
import { dateFromSerial, dateToSerial } from './core/serialDate';
|
||||
|
||||
export interface FormatterType {
|
||||
pattern: string | undefined;
|
||||
error: string;
|
||||
options: (opts?: OptionsData) => {
|
||||
overflow?: string | undefined;
|
||||
dateErrorThrows?: boolean | undefined;
|
||||
dateSpanLarge?: boolean | undefined;
|
||||
dateErrorNumber?: boolean | undefined;
|
||||
invalid?: string | undefined;
|
||||
locale?: string | undefined;
|
||||
leap1900?: boolean | undefined;
|
||||
nbsp?: boolean | undefined;
|
||||
throws?: boolean | undefined;
|
||||
ignoreTimezone?: boolean | undefined;
|
||||
};
|
||||
locale: string;
|
||||
(value: number | string | null | unknown | void, opts?: OptionsData): string;
|
||||
color(value, ops?): string;
|
||||
color(value: number | string | null | unknown | void, ops?: OptionsData | undefined): string;
|
||||
isDate(): boolean;
|
||||
isText(): boolean;
|
||||
isPercent(): boolean;
|
||||
@@ -21,7 +37,7 @@ const _cache: { [key: string]: PatternType } = {};
|
||||
function getFormatter(parseData: PatternType, initOpts: OptionsData = {}): FormatterType {
|
||||
const { pattern, partitions, locale } = parseData;
|
||||
|
||||
const getRuntimeOptions = (opts) => {
|
||||
const getRuntimeOptions = (opts: OptionsData = {}) => {
|
||||
const runOpts = { ...options(), ...initOpts, ...opts };
|
||||
if (locale) {
|
||||
runOpts.locale = locale;
|
||||
@@ -29,20 +45,20 @@ function getFormatter(parseData: PatternType, initOpts: OptionsData = {}): Forma
|
||||
return runOpts;
|
||||
};
|
||||
|
||||
const formatter = (value, opts) => {
|
||||
const formatter: FormatterType = (value: number | string | null | unknown | void, opts?: OptionsData) => {
|
||||
if (value) {
|
||||
const o = getRuntimeOptions(opts);
|
||||
return formatNumber(dateToSerial(value, o), partitions, o);
|
||||
return formatNumber(dateToSerial(value as any[] | Date, o) as string | number, partitions as PartType[], o);
|
||||
}
|
||||
return String();
|
||||
};
|
||||
formatter.color = (value, opts = {}) => {
|
||||
const o = getRuntimeOptions(opts);
|
||||
return color(dateToSerial(value, o), partitions);
|
||||
return color(dateToSerial(value as any[] | Date, o) as number, partitions as PartType[]);
|
||||
};
|
||||
formatter.isPercent = () => isPercent(partitions);
|
||||
formatter.isDate = () => isDate(partitions);
|
||||
formatter.isText = () => isText(partitions);
|
||||
formatter.isPercent = () => isPercent(partitions as PartType[]);
|
||||
formatter.isDate = () => isDate(partitions as PartType[]);
|
||||
formatter.isText = () => isText(partitions as PartType[]);
|
||||
formatter.pattern = pattern;
|
||||
if (parseData.error) {
|
||||
formatter.error = parseData.error;
|
||||
@@ -81,16 +97,16 @@ numfmt.round = round;
|
||||
numfmt.codeToLocale = codeToLocale;
|
||||
numfmt.getLocale = getLocale;
|
||||
numfmt.parseLocale = parseLocale;
|
||||
numfmt.addLocale = (options, l4e) => {
|
||||
numfmt.addLocale = (options: LocaleData, l4e: string) => {
|
||||
const c = parseLocale(l4e);
|
||||
// when locale is changed, expire all cached patterns
|
||||
delete _cache[c.lang];
|
||||
delete _cache[c.language];
|
||||
delete _cache[c.lang || ''];
|
||||
delete _cache[c.language || ''];
|
||||
return addLocale(options, c);
|
||||
};
|
||||
|
||||
// SSF interface compatibility
|
||||
function format(pattern, value, l4e, noThrows = false) {
|
||||
function format(pattern: string | undefined, value: any[] | Date, l4e: any, noThrows = false) {
|
||||
const opts = l4e && typeof l4e === 'object' ? l4e : { locale: l4e, throws: !noThrows };
|
||||
return numfmt(pattern, opts)(dateToSerial(value, opts), opts);
|
||||
}
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>UniverSheet</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<div id="universheet-demo-up"></div>
|
||||
<div id="universheet-demo-down"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,42 +0,0 @@
|
||||
import { ActionObservers, SheetActionBase, Workbook } from '@univerjs/core';
|
||||
|
||||
import { AddFilter, RemoveFilter } from '../Apply';
|
||||
import { ACTION_NAMES } from '../Const';
|
||||
import { IAddFilterActionData, IRemoveFilterActionData } from '../IData/FilterType';
|
||||
|
||||
export class AddFilterAction extends SheetActionBase<IAddFilterActionData, IRemoveFilterActionData> {
|
||||
constructor(actionData: IAddFilterActionData, workbook: Workbook, observers: ActionObservers) {
|
||||
super(
|
||||
actionData,
|
||||
{
|
||||
WorkBookUnit: workbook,
|
||||
},
|
||||
observers
|
||||
);
|
||||
this._doActionData = {
|
||||
...actionData,
|
||||
};
|
||||
this._oldActionData = {
|
||||
sheetId: this._doActionData.sheetId,
|
||||
actionName: ACTION_NAMES.ADD_FILTER_ACTION,
|
||||
};
|
||||
this.do();
|
||||
this.validate();
|
||||
}
|
||||
|
||||
redo(): void {
|
||||
AddFilter(this._doActionData.sheetId, this._doActionData.filter);
|
||||
}
|
||||
|
||||
undo(): void {
|
||||
RemoveFilter(this._oldActionData.sheetId);
|
||||
}
|
||||
|
||||
do(): void {
|
||||
this.redo();
|
||||
}
|
||||
|
||||
validate(): boolean {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
import { ActionObservers, SheetActionBase, Workbook } from '@univerjs/core';
|
||||
|
||||
import { AddFilterCriteria, RemoveFilterCriteria } from '../Apply';
|
||||
import { ACTION_NAMES } from '../Const/ACTION_NAME';
|
||||
import { IAddFilterCriteriaActionData, IRemoveFilterCriteriaAction } from '../IData/FilterType';
|
||||
|
||||
export class AddFilterCriteriaAction extends SheetActionBase<
|
||||
IAddFilterCriteriaActionData,
|
||||
IRemoveFilterCriteriaAction
|
||||
> {
|
||||
constructor(actionData: IAddFilterCriteriaActionData, workbook: Workbook, observers: ActionObservers) {
|
||||
super(
|
||||
actionData,
|
||||
{
|
||||
WorkBookUnit: workbook,
|
||||
},
|
||||
observers
|
||||
);
|
||||
this._doActionData = {
|
||||
...actionData,
|
||||
};
|
||||
this._oldActionData = {
|
||||
columnPosition: actionData.columnPosition,
|
||||
sheetId: actionData.sheetId,
|
||||
actionName: ACTION_NAMES.ADD_FILTER_CRITERIA_ACTION,
|
||||
};
|
||||
this.do();
|
||||
this.validate();
|
||||
}
|
||||
|
||||
do(): void {
|
||||
this.redo();
|
||||
}
|
||||
|
||||
redo(): void {
|
||||
AddFilterCriteria(this._doActionData.sheetId, this._doActionData.criteriaColumn);
|
||||
}
|
||||
|
||||
undo(): void {
|
||||
RemoveFilterCriteria(this._oldActionData.sheetId, this._oldActionData.columnPosition);
|
||||
}
|
||||
|
||||
validate(): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
import { ActionObservers, Nullable, SheetActionBase, Workbook } from '@univerjs/core';
|
||||
|
||||
import { AddFilter, RemoveFilter } from '../Apply';
|
||||
import { ACTION_NAMES } from '../Const';
|
||||
import { IAddFilterActionData, IFilter, IRemoveFilterActionData } from '../IData/FilterType';
|
||||
|
||||
export class RemoveFilterAction extends SheetActionBase<IRemoveFilterActionData, IAddFilterActionData> {
|
||||
constructor(actionData: IRemoveFilterActionData, workbook: Workbook, observers: ActionObservers) {
|
||||
super(
|
||||
actionData,
|
||||
{
|
||||
WorkBookUnit: workbook,
|
||||
},
|
||||
observers
|
||||
);
|
||||
this._doActionData = {
|
||||
...actionData,
|
||||
};
|
||||
this._oldActionData = {
|
||||
sheetId: this._doActionData.sheetId,
|
||||
actionName: ACTION_NAMES.REMOVE_FILTER_ACTION,
|
||||
filter: this.do(),
|
||||
};
|
||||
this.validate();
|
||||
}
|
||||
|
||||
redo(): Nullable<IFilter> {
|
||||
return RemoveFilter(this._doActionData.sheetId);
|
||||
}
|
||||
|
||||
undo(): void {
|
||||
AddFilter(this._doActionData.sheetId, this._oldActionData.filter);
|
||||
}
|
||||
|
||||
do(): Nullable<IFilter> {
|
||||
return this.redo();
|
||||
}
|
||||
|
||||
validate(): boolean {
|
||||
throw new Error('Method not implemented.');
|
||||
}
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
import { ActionObservers, Nullable, SheetActionBase, Workbook } from '@univerjs/core';
|
||||
|
||||
import { AddFilterCriteria, RemoveFilterCriteria } from '../Apply';
|
||||
import { ACTION_NAMES } from '../Const';
|
||||
import { IAddFilterCriteriaActionData, IFilterCriteriaColumn, IRemoveFilterCriteriaAction } from '../IData/FilterType';
|
||||
|
||||
export class RemoveFilterCriteriaAction extends SheetActionBase<
|
||||
IRemoveFilterCriteriaAction,
|
||||
IAddFilterCriteriaActionData
|
||||
> {
|
||||
constructor(actionData: IRemoveFilterCriteriaAction, workbook: Workbook, observers: ActionObservers) {
|
||||
super(
|
||||
actionData,
|
||||
{
|
||||
WorkBookUnit: workbook,
|
||||
},
|
||||
observers
|
||||
);
|
||||
this._doActionData = {
|
||||
...actionData,
|
||||
};
|
||||
this._oldActionData = {
|
||||
actionName: ACTION_NAMES.ADD_FILTER_CRITERIA_ACTION,
|
||||
sheetId: actionData.sheetId,
|
||||
columnPosition: actionData.columnPosition,
|
||||
criteriaColumn: this.do(),
|
||||
};
|
||||
this.validate();
|
||||
}
|
||||
|
||||
do(): Nullable<IFilterCriteriaColumn> {
|
||||
return this.redo();
|
||||
}
|
||||
|
||||
redo(): Nullable<IFilterCriteriaColumn> {
|
||||
return RemoveFilterCriteria(this._oldActionData.sheetId, this._doActionData.columnPosition);
|
||||
}
|
||||
|
||||
undo(): void {
|
||||
AddFilterCriteria(this._doActionData.sheetId, this._oldActionData.criteriaColumn);
|
||||
}
|
||||
|
||||
validate(): boolean {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
export * from './AddFilterAction';
|
||||
export * from './AddFilterCriteriaAction';
|
||||
export * from './RemoveFilterAction';
|
||||
export * from './RemoveFilterCriteriaAction';
|
||||
@@ -1,14 +1,8 @@
|
||||
import { BaseComponentProps } from '@univerjs/base-ui/src/BaseComponent';
|
||||
import { SheetContext } from '@univerjs/core';
|
||||
import { BaseComponentProps } from '@univerjs/base-ui';
|
||||
|
||||
import { FilterPlugin } from './FilterPlugin';
|
||||
|
||||
export type IConfig = {
|
||||
context: SheetContext;
|
||||
};
|
||||
|
||||
// Types for props
|
||||
export interface IProps extends BaseComponentProps {
|
||||
config: IConfig;
|
||||
super: FilterPlugin;
|
||||
}
|
||||
|
||||
@@ -1,13 +1,4 @@
|
||||
import {
|
||||
Color,
|
||||
ConditionType,
|
||||
IColor,
|
||||
ISelectionRange,
|
||||
ISheetActionData,
|
||||
Nullable,
|
||||
RelativeDate,
|
||||
Sequence,
|
||||
} from '@univerjs/core';
|
||||
import { Color, ConditionType, IColor, ISelectionRange, Nullable, RelativeDate, Sequence } from '@univerjs/core';
|
||||
|
||||
import { BooleanCriteria } from '../Enum/BooleanCriteria';
|
||||
|
||||
@@ -58,7 +49,7 @@ export interface IFilter extends Sequence {
|
||||
};
|
||||
}
|
||||
|
||||
export interface IAddFilterActionData extends ISheetActionData {
|
||||
export interface IAddFilterActionData {
|
||||
filter: Nullable<IFilter>;
|
||||
}
|
||||
|
||||
@@ -67,14 +58,14 @@ export interface IFilterCriteriaColumn extends Sequence {
|
||||
criteria: IFilterCriteriaData;
|
||||
}
|
||||
|
||||
export interface IAddFilterCriteriaActionData extends ISheetActionData {
|
||||
export interface IAddFilterCriteriaActionData {
|
||||
columnPosition: number;
|
||||
criteriaColumn: Nullable<IFilterCriteriaColumn>;
|
||||
}
|
||||
|
||||
export interface IRemoveFilterActionData extends ISheetActionData {}
|
||||
export interface IRemoveFilterActionData {}
|
||||
|
||||
export interface IRemoveFilterCriteriaAction extends ISheetActionData {
|
||||
export interface IRemoveFilterCriteriaAction {
|
||||
columnPosition: number;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,4 +1,12 @@
|
||||
import { BaseSelectProps, Icon, Select } from '@univerjs/base-ui';
|
||||
import {
|
||||
AppContext,
|
||||
IMenuSelectorItem,
|
||||
IValueOption,
|
||||
MenuItemType,
|
||||
MenuPosition,
|
||||
Select,
|
||||
SelectTypes,
|
||||
} from '@univerjs/base-ui';
|
||||
import { Nullable, Observer, Workbook } from '@univerjs/core';
|
||||
import { Component } from 'react';
|
||||
|
||||
@@ -6,12 +14,14 @@ import { FilterPlugin } from '../FilterPlugin';
|
||||
import { IProps } from '../IData';
|
||||
|
||||
interface IState {
|
||||
filter: IToolbarItemProps;
|
||||
filter: IMenuSelectorItem<unknown>;
|
||||
isFilter: boolean;
|
||||
filterPlugin: FilterPlugin | null;
|
||||
}
|
||||
|
||||
export class FilterButton extends Component<IProps, IState> {
|
||||
static override contextType = AppContext;
|
||||
|
||||
protected _localeObserver: Nullable<Observer<Workbook>>;
|
||||
|
||||
constructor(props: IProps) {
|
||||
@@ -22,21 +32,22 @@ export class FilterButton extends Component<IProps, IState> {
|
||||
initialize(props: IProps) {
|
||||
this.state = {
|
||||
filter: {
|
||||
locale: 'filter',
|
||||
type: 'select',
|
||||
label: <Icon.Data.FilterRankIcon />,
|
||||
icon: <Icon.NextIcon />,
|
||||
show: true,
|
||||
children: [
|
||||
id: 'filter',
|
||||
title: 'filter',
|
||||
type: MenuItemType.SELECTOR,
|
||||
selectType: SelectTypes.NEO,
|
||||
positions: [MenuPosition.TOOLBAR],
|
||||
icon: 'FilterRankIcon',
|
||||
selections: [
|
||||
{
|
||||
locale: 'filter.filter',
|
||||
icon: <Icon.Data.FilterIcon />,
|
||||
onClick: () => {},
|
||||
label: 'filter.filter',
|
||||
value: 'filter',
|
||||
// icon: 'FilterIcon',
|
||||
},
|
||||
{
|
||||
locale: 'filter.clearFilter',
|
||||
icon: <Icon.Data.CleanIcon />,
|
||||
onClick: () => {},
|
||||
label: 'filter.clearFilter',
|
||||
value: 'clearFilter',
|
||||
// icon: 'CleanIcon',
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -56,39 +67,38 @@ export class FilterButton extends Component<IProps, IState> {
|
||||
this.setLocale();
|
||||
|
||||
// subscribe Locale change event
|
||||
this._localeObserver = this.context.observerManager
|
||||
.requiredObserver('onAfterChangeUILocaleObservable', 'core')
|
||||
?.add(() => {
|
||||
this.setLocale();
|
||||
});
|
||||
const observerManager = (this.context as any).injector!.get('observerManager');
|
||||
this._localeObserver = observerManager.requiredObserver('onAfterChangeUILocaleObservable', 'core')?.add(() => {
|
||||
this.setLocale();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* destory
|
||||
*/
|
||||
override componentWillUnmount() {
|
||||
this.context.observerManager
|
||||
.requiredObserver('onAfterChangeUILocaleObservable', 'core')
|
||||
?.remove(this._localeObserver);
|
||||
const observerManager = (this.context as any).injector!.get('observerManager');
|
||||
observerManager.requiredObserver('onAfterChangeUILocaleObservable', 'core')?.remove(this._localeObserver);
|
||||
}
|
||||
|
||||
/**
|
||||
* set text by config setting and Locale message
|
||||
*/
|
||||
setLocale() {
|
||||
const locale = this.context.localeService.getLocale();
|
||||
const locale = (this.context as any).injector!.get('localeService');
|
||||
// const locale = this.context.localeService.getLocale();
|
||||
this.setState((prevState: IState) => {
|
||||
const item = prevState.filter;
|
||||
// set current Locale string for tooltip
|
||||
item.tooltip = locale.get(`${item.locale}Label`);
|
||||
item.tooltip = locale.get(`${item.title}Label`);
|
||||
|
||||
// set current Locale string for select
|
||||
item.children?.forEach((ele: IToolbarItemProps) => {
|
||||
if (ele.locale) {
|
||||
ele.label = locale.get(`${ele.locale}`);
|
||||
(item.selections as IValueOption[])?.forEach((ele) => {
|
||||
if (ele.label) {
|
||||
ele.label = locale.get(`${ele.label}`);
|
||||
}
|
||||
});
|
||||
item.label = typeof item.label === 'object' ? item.label : item.children![0].label;
|
||||
item.label = typeof item.label === 'object' ? item.label : (item.selections![0] as IValueOption).label;
|
||||
|
||||
return {
|
||||
filter: item,
|
||||
@@ -101,16 +111,8 @@ export class FilterButton extends Component<IProps, IState> {
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
render() {
|
||||
override render() {
|
||||
const { filter } = this.state;
|
||||
return (
|
||||
<Select
|
||||
tooltip={filter.tooltip}
|
||||
key={filter.locale}
|
||||
children={filter.children as BaseSelectProps[]}
|
||||
label={filter.label}
|
||||
icon={filter.icon}
|
||||
/>
|
||||
);
|
||||
return <Select tooltip={filter.tooltip} children={filter.selections as IValueOption[]} icon={filter.icon} />;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
import { RenderEngine } from '@univerjs/base-render';
|
||||
import { DEFAULT_WORKBOOK_DATA } from '@univerjs/common-plugin-data';
|
||||
import { UniverSheet } from '@univerjs/core';
|
||||
|
||||
const uiDefaultConfigUp = {
|
||||
container: 'universheet-demo-up',
|
||||
};
|
||||
|
||||
const univerSheetUp = UniverSheet.newInstance(DEFAULT_WORKBOOK_DATA);
|
||||
univerSheetUp.installPlugin(new RenderEngine());
|
||||
// univerSheetUp.installPlugin(new UniverComponentSheet());
|
||||
// univerSheetUp.installPlugin(new SheetPlugin(uiDefaultConfigUp));
|
||||
// univerSheetUp.installPlugin(new FilterPlugin());
|
||||
@@ -1,18 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="icon" type="image/svg+xml" href="favicon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>UniverSheet</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="app"></div>
|
||||
<div id="universheet-demo-up"></div>
|
||||
<div id="universheet-demo-down"></div>
|
||||
<script type="module" src="/src/main.tsx"></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,16 +0,0 @@
|
||||
import { Observable } from '@univerjs/core';
|
||||
|
||||
import { NumfmtPlugin } from '../NumfmtPlugin';
|
||||
import { NumfmtModal } from '../View/UI/NumfmtModal';
|
||||
|
||||
export type NumfmtPluginObserve = {
|
||||
onNumfmtModalDidMountObservable: Observable<NumfmtModal>;
|
||||
};
|
||||
|
||||
export function uninstall(plugin: NumfmtPlugin) {
|
||||
plugin.deleteObserve('onNumfmtModalDidMountObservable');
|
||||
}
|
||||
|
||||
export function install(plugin: NumfmtPlugin) {
|
||||
plugin.pushToObserve('onNumfmtModalDidMountObservable');
|
||||
}
|
||||
@@ -1,3 +1,2 @@
|
||||
// @index('./*.ts', f => `export * from '${f.path}'`)
|
||||
export * from './NumfmtActionExtension';
|
||||
// @endindex
|
||||
|
||||
@@ -1,3 +1,2 @@
|
||||
export * from './Const';
|
||||
export * from './Enum';
|
||||
export * from './Observer';
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
import { ComponentChildren, ComponentManager } from '@univerjs/base-ui';
|
||||
import { ComponentManager } from '@univerjs/base-ui';
|
||||
import { LocaleService, ObserverManager } from '@univerjs/core';
|
||||
import { Inject } from '@wendellhu/redi';
|
||||
import React from 'react';
|
||||
|
||||
import { CURRENCYDETAIL, DATEFMTLISG, NUMBERFORMAT, NUMFMT_PLUGIN_NAME } from '../Basics/Const';
|
||||
import { NumfmtModel } from '../Model/NumfmtModel';
|
||||
import { INumfmtPluginData } from '../Symbol';
|
||||
import { FormatContent } from '../View/UI/FormatContent';
|
||||
import { NumfmtModal } from '../View/UI/NumfmtModal';
|
||||
@@ -24,7 +26,7 @@ export interface ModalDataProps {
|
||||
props: any;
|
||||
};
|
||||
group: GroupProps[];
|
||||
modal?: ComponentChildren; // 渲染的组件
|
||||
modal?: React.ReactNode; // 渲染的组件
|
||||
onCancel?: () => void;
|
||||
}
|
||||
|
||||
@@ -117,10 +119,9 @@ export class NumfmtModalController {
|
||||
];
|
||||
this._componentManager.register(NUMFMT_PLUGIN_NAME + FormatContent.name, FormatContent);
|
||||
this._componentManager.register(NUMFMT_PLUGIN_NAME + NumfmtModal.name, NumfmtModal);
|
||||
this._observerManager.getObserver<NumfmtModal>('onNumfmtModalDidMountObservable')!.add((component): void => {
|
||||
this._numfmtModal = component;
|
||||
this.resetModalData();
|
||||
});
|
||||
// this._observerManager.getObserver<NumfmtModal>('onNumfmtModalDidMountObservable')!.add((component): void => {
|
||||
// this.resetModalData();
|
||||
// });
|
||||
}
|
||||
|
||||
resetContentData(data: any[]): any[] {
|
||||
@@ -144,7 +145,9 @@ export class NumfmtModalController {
|
||||
});
|
||||
}
|
||||
});
|
||||
this._numfmtPluginData.setModal(this._modalData);
|
||||
|
||||
// TODO update modal data
|
||||
// this._numfmtPluginData.setModal(this._modalData);
|
||||
}
|
||||
|
||||
showModal(name: string, show: boolean): void {
|
||||
|
||||
@@ -1 +1 @@
|
||||
export * from './SetNumfmtRangeDataAction';
|
||||
// export * from './SetNumfmtRangeDataAction';
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { ISelectionRange, LocaleService, ObjectMatrixPrimitiveType, Plugin, PluginType } from '@univerjs/core';
|
||||
import { Dependency, Inject, Injector } from '@wendellhu/redi';
|
||||
|
||||
import { install, NUMFMT_PLUGIN_NAME, NumfmtActionExtensionFactory } from './Basics';
|
||||
import { NUMFMT_PLUGIN_NAME } from './Basics';
|
||||
import { NumfmtController, NumfmtModalController } from './Controller';
|
||||
import { INumfmtPluginConfig } from './Interfaces';
|
||||
import en from './Locale/en';
|
||||
@@ -18,8 +18,6 @@ export class NumfmtPlugin extends Plugin {
|
||||
|
||||
private _numfmtPluginData: NumfmtModel;
|
||||
|
||||
private _numfmtActionExtensionFactory: NumfmtActionExtensionFactory;
|
||||
|
||||
constructor(
|
||||
config: Partial<INumfmtPluginConfig>,
|
||||
@Inject(LocaleService) private readonly _localeService: LocaleService,
|
||||
@@ -32,7 +30,6 @@ export class NumfmtPlugin extends Plugin {
|
||||
}
|
||||
|
||||
override onRendered(): void {
|
||||
install(this);
|
||||
this.initializeDependencies(this._injector);
|
||||
this.registerExtension();
|
||||
this._numfmtController = this._injector.get(NumfmtController);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { Input } from '@univerjs/base-ui';
|
||||
import { Component, createRef } from 'react';
|
||||
|
||||
import styles from './index.module.less';
|
||||
@@ -12,7 +13,7 @@ interface IProps {
|
||||
interface IState {}
|
||||
|
||||
export class FormatContent extends Component<IProps, IState> {
|
||||
private _ref = createRef();
|
||||
private _ref = createRef<HTMLDivElement>();
|
||||
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
@@ -21,22 +22,9 @@ export class FormatContent extends Component<IProps, IState> {
|
||||
|
||||
initialize(props: IProps) {}
|
||||
|
||||
getInput() {
|
||||
const { input } = this.props;
|
||||
const Input = this._render.renderFunction('Input');
|
||||
|
||||
if (input) {
|
||||
return (
|
||||
<div className={styles.formatInput}>
|
||||
<span>{input}:</span>
|
||||
<Input type="number" value="2" onChange={this.handleChange.bind(this)}></Input>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
handleClick(value: string, index: number) {
|
||||
const lis = this._ref.current.querySelectorAll('li');
|
||||
const lis = this._ref.current?.querySelectorAll('li');
|
||||
if (!lis) return;
|
||||
for (let i = 0; i < lis.length; i++) {
|
||||
lis[i].classList.remove(styles.formatSelected);
|
||||
}
|
||||
@@ -46,7 +34,7 @@ export class FormatContent extends Component<IProps, IState> {
|
||||
this.props.onClick(value);
|
||||
}
|
||||
|
||||
handleChange(e: Event) {
|
||||
handleChange(e: React.ChangeEvent<HTMLInputElement>) {
|
||||
const value = (e.target as HTMLInputElement).value;
|
||||
this.props.onChange?.(value);
|
||||
}
|
||||
@@ -56,22 +44,26 @@ export class FormatContent extends Component<IProps, IState> {
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
render() {
|
||||
// const { data } = this.props;
|
||||
//
|
||||
// return (
|
||||
// <div className={styles.formatContent} ref={this._ref}>
|
||||
// {this.getInput()}
|
||||
// <ul>
|
||||
// {data.map((item, index) => (
|
||||
// <li onClick={() => this.handleClick(item.value, index)}>
|
||||
// <span>{item.label}</span>
|
||||
// <span>{item.suffix}</span>
|
||||
// </li>
|
||||
// ))}
|
||||
// </ul>
|
||||
// </div>
|
||||
// );
|
||||
return <></>;
|
||||
override render() {
|
||||
const { data, input } = this.props;
|
||||
|
||||
return (
|
||||
<div className={styles.formatContent} ref={this._ref}>
|
||||
input && (
|
||||
<div className={styles.formatInput}>
|
||||
<span>{input}:</span>
|
||||
<Input type="number" value="2" onChange={this.handleChange.bind(this)}></Input>
|
||||
</div>
|
||||
)
|
||||
<ul>
|
||||
{data.map((item, index) => (
|
||||
<li onClick={() => this.handleClick(item.value, index)}>
|
||||
<span>{item.label}</span>
|
||||
<span>{item.suffix}</span>
|
||||
</li>
|
||||
))}
|
||||
</ul>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { AppContext, AppContextValues, BaseMenuItem, Icon, joinClassNames } from '@univerjs/base-ui';
|
||||
import { ComponentChildren, useContext } from 'react';
|
||||
import React, { useContext } from 'react';
|
||||
|
||||
import styles from './FormatItem.module.less';
|
||||
|
||||
export interface BaseFormatItemProps extends BaseMenuItem {
|
||||
selected?: boolean;
|
||||
labelText?: string;
|
||||
suffix?: ComponentChildren;
|
||||
suffix?: React.ReactNode;
|
||||
border?: boolean;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
import { SheetPlugin } from '@univerjs/base-sheets';
|
||||
import { BaseComponentProps } from '@univerjs/base-ui';
|
||||
import { PLUGIN_NAMES } from '@univerjs/core';
|
||||
import { AppContext, BaseComponentProps, ComponentManager } from '@univerjs/base-ui';
|
||||
import { Component } from 'react';
|
||||
|
||||
import { NUMFMT_PLUGIN_NAME } from '../../Basics/Const';
|
||||
import { ModalDataProps } from '../../Controller/NumfmtModalController';
|
||||
import { NumfmtPlugin } from '../../NumfmtPlugin';
|
||||
|
||||
interface IProps extends BaseComponentProps {}
|
||||
|
||||
@@ -14,6 +10,8 @@ interface IState {
|
||||
}
|
||||
|
||||
export class NumfmtModal extends Component<IProps, IState> {
|
||||
static override contextType = AppContext;
|
||||
|
||||
constructor(props: IProps) {
|
||||
super(props);
|
||||
this.initialize(props);
|
||||
@@ -25,17 +23,12 @@ export class NumfmtModal extends Component<IProps, IState> {
|
||||
};
|
||||
}
|
||||
|
||||
override componentDidMount(): void {
|
||||
const plugin = this.getContext().getPluginManager().getPluginByName<NumfmtPlugin>(NUMFMT_PLUGIN_NAME)!;
|
||||
plugin.getObserver('onNumfmtModalDidMountObservable')!.notifyObservers(this);
|
||||
}
|
||||
override componentDidMount(): void {}
|
||||
|
||||
setModal(modalData: ModalDataProps[]): void {
|
||||
const SheetPlugin: SheetPlugin = this.getContext()
|
||||
.getPluginManager()
|
||||
.getPluginByName<SheetPlugin>(PLUGIN_NAMES.SPREADSHEET)!;
|
||||
const componentManager: ComponentManager = (this.context as any).injector.get(ComponentManager);
|
||||
modalData.forEach((item): void => {
|
||||
const Label = this.context.componentManager.get(item.children.name);
|
||||
const Label = componentManager.get(item.children.name) as JSX.ElementType;
|
||||
if (Label) {
|
||||
const props = item.children.props ?? {};
|
||||
item.modal = <Label {...props} />;
|
||||
@@ -49,7 +42,7 @@ export class NumfmtModal extends Component<IProps, IState> {
|
||||
*
|
||||
* @returns {void}
|
||||
*/
|
||||
render() {
|
||||
override render() {
|
||||
// const Modal = this._render.renderFunction('Modal');
|
||||
// const { modalData } = this.state;
|
||||
// // Set Provider for entire Container
|
||||
|
||||
@@ -1,45 +0,0 @@
|
||||
.format-content .format-input {
|
||||
display: flex;
|
||||
}
|
||||
.format-content .format-input input {
|
||||
width: 80px;
|
||||
height: 24px;
|
||||
padding: 0 5px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
.format-content ul {
|
||||
height: 240px;
|
||||
border: 1px solid var(--gray-5);
|
||||
overflow-y: auto;
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
}
|
||||
.format-content ul li {
|
||||
height: 30px;
|
||||
padding: 0 20px;
|
||||
border-bottom: 1px solid #dfdfdf;
|
||||
line-height: 30px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.format-content ul .format-selected {
|
||||
color: #fff;
|
||||
background: var(--primary-color);
|
||||
}
|
||||
.custom-format .drop-content {
|
||||
width: 60px;
|
||||
}
|
||||
.custom-format .drop-content > div {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.custom-format .select-item-content {
|
||||
margin-right: 15px;
|
||||
}
|
||||
.custom-format .custom-format-more .select-item-suffix span[role='img'] {
|
||||
font-size: 16px;
|
||||
}
|
||||
.custom-format .custom-format-more ul .select-item {
|
||||
padding: 0 14px 0 14px;
|
||||
}
|
||||
Reference in New Issue
Block a user