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:
Dushusir
2023-09-27 17:58:42 +08:00
committed by GitHub
parent 7a77092968
commit 7dccc8ecf1
29 changed files with 173 additions and 476 deletions
@@ -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);
+17 -17
View File
@@ -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);
}
+29 -13
View File
@@ -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);
}
-18
View File
@@ -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 -7
View File
@@ -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());
-18
View File
@@ -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;
}