@dxos/plugin-sheet 0.6.8-main.046e6cf

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (147) hide show
  1. package/LICENSE +8 -0
  2. package/README.md +14 -0
  3. package/dist/lib/browser/SheetContainer-H22IDJ43.mjs +3740 -0
  4. package/dist/lib/browser/SheetContainer-H22IDJ43.mjs.map +7 -0
  5. package/dist/lib/browser/chunk-6VPEAUG6.mjs +82 -0
  6. package/dist/lib/browser/chunk-6VPEAUG6.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-AT2FJXQX.mjs +861 -0
  8. package/dist/lib/browser/chunk-AT2FJXQX.mjs.map +7 -0
  9. package/dist/lib/browser/chunk-JRL5LGCE.mjs +18 -0
  10. package/dist/lib/browser/chunk-JRL5LGCE.mjs.map +7 -0
  11. package/dist/lib/browser/index.mjs +213 -0
  12. package/dist/lib/browser/index.mjs.map +7 -0
  13. package/dist/lib/browser/meta.json +1 -0
  14. package/dist/lib/browser/meta.mjs +9 -0
  15. package/dist/lib/browser/meta.mjs.map +7 -0
  16. package/dist/lib/browser/types.mjs +22 -0
  17. package/dist/lib/browser/types.mjs.map +7 -0
  18. package/dist/lib/node/SheetContainer-S32KTNZ6.cjs +3731 -0
  19. package/dist/lib/node/SheetContainer-S32KTNZ6.cjs.map +7 -0
  20. package/dist/lib/node/chunk-4CE6FK5Z.cjs +108 -0
  21. package/dist/lib/node/chunk-4CE6FK5Z.cjs.map +7 -0
  22. package/dist/lib/node/chunk-BJ6ZD7MN.cjs +51 -0
  23. package/dist/lib/node/chunk-BJ6ZD7MN.cjs.map +7 -0
  24. package/dist/lib/node/chunk-FCKJ4QRM.cjs +881 -0
  25. package/dist/lib/node/chunk-FCKJ4QRM.cjs.map +7 -0
  26. package/dist/lib/node/index.cjs +226 -0
  27. package/dist/lib/node/index.cjs.map +7 -0
  28. package/dist/lib/node/meta.cjs +30 -0
  29. package/dist/lib/node/meta.cjs.map +7 -0
  30. package/dist/lib/node/meta.json +1 -0
  31. package/dist/lib/node/types.cjs +44 -0
  32. package/dist/lib/node/types.cjs.map +7 -0
  33. package/dist/types/src/SheetPlugin.d.ts +4 -0
  34. package/dist/types/src/SheetPlugin.d.ts.map +1 -0
  35. package/dist/types/src/components/CellEditor/CellEditor.d.ts +14 -0
  36. package/dist/types/src/components/CellEditor/CellEditor.d.ts.map +1 -0
  37. package/dist/types/src/components/CellEditor/CellEditor.stories.d.ts +29 -0
  38. package/dist/types/src/components/CellEditor/CellEditor.stories.d.ts.map +1 -0
  39. package/dist/types/src/components/CellEditor/extension.d.ts +18 -0
  40. package/dist/types/src/components/CellEditor/extension.d.ts.map +1 -0
  41. package/dist/types/src/components/CellEditor/extension.test.d.ts +2 -0
  42. package/dist/types/src/components/CellEditor/extension.test.d.ts.map +1 -0
  43. package/dist/types/src/components/CellEditor/functions.d.ts +66 -0
  44. package/dist/types/src/components/CellEditor/functions.d.ts.map +1 -0
  45. package/dist/types/src/components/CellEditor/index.d.ts +3 -0
  46. package/dist/types/src/components/CellEditor/index.d.ts.map +1 -0
  47. package/dist/types/src/components/ComputeGraph/async-function.d.ts +52 -0
  48. package/dist/types/src/components/ComputeGraph/async-function.d.ts.map +1 -0
  49. package/dist/types/src/components/ComputeGraph/custom.d.ts +21 -0
  50. package/dist/types/src/components/ComputeGraph/custom.d.ts.map +1 -0
  51. package/dist/types/src/components/ComputeGraph/edge-function.d.ts +20 -0
  52. package/dist/types/src/components/ComputeGraph/edge-function.d.ts.map +1 -0
  53. package/dist/types/src/components/ComputeGraph/graph-context.d.ts +11 -0
  54. package/dist/types/src/components/ComputeGraph/graph-context.d.ts.map +1 -0
  55. package/dist/types/src/components/ComputeGraph/graph.browser.test.d.ts +2 -0
  56. package/dist/types/src/components/ComputeGraph/graph.browser.test.d.ts.map +1 -0
  57. package/dist/types/src/components/ComputeGraph/graph.d.ts +21 -0
  58. package/dist/types/src/components/ComputeGraph/graph.d.ts.map +1 -0
  59. package/dist/types/src/components/ComputeGraph/index.d.ts +4 -0
  60. package/dist/types/src/components/ComputeGraph/index.d.ts.map +1 -0
  61. package/dist/types/src/components/Sheet/Sheet.d.ts +55 -0
  62. package/dist/types/src/components/Sheet/Sheet.d.ts.map +1 -0
  63. package/dist/types/src/components/Sheet/Sheet.stories.d.ts +54 -0
  64. package/dist/types/src/components/Sheet/Sheet.stories.d.ts.map +1 -0
  65. package/dist/types/src/components/Sheet/formatting.d.ts +14 -0
  66. package/dist/types/src/components/Sheet/formatting.d.ts.map +1 -0
  67. package/dist/types/src/components/Sheet/grid.d.ts +52 -0
  68. package/dist/types/src/components/Sheet/grid.d.ts.map +1 -0
  69. package/dist/types/src/components/Sheet/index.d.ts +2 -0
  70. package/dist/types/src/components/Sheet/index.d.ts.map +1 -0
  71. package/dist/types/src/components/Sheet/nav.d.ts +29 -0
  72. package/dist/types/src/components/Sheet/nav.d.ts.map +1 -0
  73. package/dist/types/src/components/Sheet/sheet-context.d.ts +24 -0
  74. package/dist/types/src/components/Sheet/sheet-context.d.ts.map +1 -0
  75. package/dist/types/src/components/Sheet/util.d.ts +18 -0
  76. package/dist/types/src/components/Sheet/util.d.ts.map +1 -0
  77. package/dist/types/src/components/SheetContainer.d.ts +9 -0
  78. package/dist/types/src/components/SheetContainer.d.ts.map +1 -0
  79. package/dist/types/src/components/Toolbar/Toolbar.d.ts +21 -0
  80. package/dist/types/src/components/Toolbar/Toolbar.d.ts.map +1 -0
  81. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts +35 -0
  82. package/dist/types/src/components/Toolbar/Toolbar.stories.d.ts.map +1 -0
  83. package/dist/types/src/components/Toolbar/common.d.ts +20 -0
  84. package/dist/types/src/components/Toolbar/common.d.ts.map +1 -0
  85. package/dist/types/src/components/Toolbar/index.d.ts +2 -0
  86. package/dist/types/src/components/Toolbar/index.d.ts.map +1 -0
  87. package/dist/types/src/components/index.d.ts +7 -0
  88. package/dist/types/src/components/index.d.ts.map +1 -0
  89. package/dist/types/src/index.d.ts +4 -0
  90. package/dist/types/src/index.d.ts.map +1 -0
  91. package/dist/types/src/meta.d.ts +15 -0
  92. package/dist/types/src/meta.d.ts.map +1 -0
  93. package/dist/types/src/model/index.d.ts +3 -0
  94. package/dist/types/src/model/index.d.ts.map +1 -0
  95. package/dist/types/src/model/model.browser.test.d.ts +2 -0
  96. package/dist/types/src/model/model.browser.test.d.ts.map +1 -0
  97. package/dist/types/src/model/model.d.ts +142 -0
  98. package/dist/types/src/model/model.d.ts.map +1 -0
  99. package/dist/types/src/model/types.d.ts +17 -0
  100. package/dist/types/src/model/types.d.ts.map +1 -0
  101. package/dist/types/src/model/types.test.d.ts +2 -0
  102. package/dist/types/src/model/types.test.d.ts.map +1 -0
  103. package/dist/types/src/model/util.d.ts +15 -0
  104. package/dist/types/src/model/util.d.ts.map +1 -0
  105. package/dist/types/src/translations.d.ts +16 -0
  106. package/dist/types/src/translations.d.ts.map +1 -0
  107. package/dist/types/src/types.d.ts +94 -0
  108. package/dist/types/src/types.d.ts.map +1 -0
  109. package/package.json +122 -0
  110. package/src/SheetPlugin.tsx +150 -0
  111. package/src/components/CellEditor/CellEditor.stories.tsx +88 -0
  112. package/src/components/CellEditor/CellEditor.tsx +113 -0
  113. package/src/components/CellEditor/extension.test.ts +42 -0
  114. package/src/components/CellEditor/extension.ts +286 -0
  115. package/src/components/CellEditor/functions.ts +2017 -0
  116. package/src/components/CellEditor/index.ts +6 -0
  117. package/src/components/ComputeGraph/async-function.ts +148 -0
  118. package/src/components/ComputeGraph/custom.ts +70 -0
  119. package/src/components/ComputeGraph/edge-function.ts +60 -0
  120. package/src/components/ComputeGraph/graph-context.tsx +37 -0
  121. package/src/components/ComputeGraph/graph.browser.test.ts +49 -0
  122. package/src/components/ComputeGraph/graph.ts +52 -0
  123. package/src/components/ComputeGraph/index.ts +7 -0
  124. package/src/components/Sheet/Sheet.stories.tsx +329 -0
  125. package/src/components/Sheet/Sheet.tsx +1164 -0
  126. package/src/components/Sheet/formatting.ts +106 -0
  127. package/src/components/Sheet/grid.ts +191 -0
  128. package/src/components/Sheet/index.ts +5 -0
  129. package/src/components/Sheet/nav.ts +157 -0
  130. package/src/components/Sheet/sheet-context.tsx +101 -0
  131. package/src/components/Sheet/util.ts +56 -0
  132. package/src/components/SheetContainer.tsx +30 -0
  133. package/src/components/Toolbar/Toolbar.stories.tsx +36 -0
  134. package/src/components/Toolbar/Toolbar.tsx +198 -0
  135. package/src/components/Toolbar/common.tsx +72 -0
  136. package/src/components/Toolbar/index.ts +5 -0
  137. package/src/components/index.ts +10 -0
  138. package/src/index.ts +9 -0
  139. package/src/meta.tsx +18 -0
  140. package/src/model/index.ts +6 -0
  141. package/src/model/model.browser.test.ts +100 -0
  142. package/src/model/model.ts +480 -0
  143. package/src/model/types.test.ts +92 -0
  144. package/src/model/types.ts +71 -0
  145. package/src/model/util.ts +36 -0
  146. package/src/translations.ts +22 -0
  147. package/src/types.ts +110 -0
@@ -0,0 +1,198 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import {
6
+ type Icon,
7
+ Calendar,
8
+ ChatText,
9
+ CurrencyDollar,
10
+ Eraser,
11
+ HighlighterCircle,
12
+ TextAlignCenter,
13
+ TextAlignLeft,
14
+ TextAlignRight,
15
+ } from '@phosphor-icons/react';
16
+ import { createContext } from '@radix-ui/react-context';
17
+ import React, { type PropsWithChildren } from 'react';
18
+
19
+ import {
20
+ DensityProvider,
21
+ ElevationProvider,
22
+ Toolbar as NaturalToolbar,
23
+ type ThemedClassName,
24
+ useTranslation,
25
+ } from '@dxos/react-ui';
26
+
27
+ import { ToolbarButton, ToolbarSeparator, ToolbarToggleButton } from './common';
28
+ import { SHEET_PLUGIN } from '../../meta';
29
+ import { type Formatting } from '../../types';
30
+
31
+ //
32
+ // Root
33
+ //
34
+
35
+ export type ToolbarActionType = 'clear' | 'highlight' | 'left' | 'center' | 'right' | 'date' | 'currency';
36
+
37
+ export type ToolbarAction = {
38
+ type: ToolbarActionType;
39
+ };
40
+
41
+ export type ToolbarActionHandler = ({ type }: ToolbarAction) => void;
42
+
43
+ export type ToolbarProps = ThemedClassName<
44
+ PropsWithChildren<{
45
+ onAction?: ToolbarActionHandler;
46
+ }>
47
+ >;
48
+
49
+ const [ToolbarContextProvider, useToolbarContext] = createContext<ToolbarProps>('Toolbar');
50
+
51
+ const ToolbarRoot = ({ children, onAction, classNames }: ToolbarProps) => {
52
+ return (
53
+ <ToolbarContextProvider onAction={onAction}>
54
+ <DensityProvider density='fine'>
55
+ <ElevationProvider elevation='chrome'>
56
+ <NaturalToolbar.Root classNames={['is-full shrink-0 overflow-x-auto overflow-y-hidden p-1', classNames]}>
57
+ {children}
58
+ </NaturalToolbar.Root>
59
+ </ElevationProvider>
60
+ </DensityProvider>
61
+ </ToolbarContextProvider>
62
+ );
63
+ };
64
+
65
+ // TODO(burdon): Generalize.
66
+ // TODO(burdon): Detect and display current state.
67
+ type ButtonProps = {
68
+ type: ToolbarActionType;
69
+ Icon: Icon;
70
+ getState: (state: Formatting) => boolean;
71
+ disabled?: (state: Formatting) => boolean;
72
+ };
73
+
74
+ //
75
+ // Alignment
76
+ //
77
+
78
+ const formatOptions: ButtonProps[] = [
79
+ { type: 'date', Icon: Calendar, getState: (state) => false },
80
+ { type: 'currency', Icon: CurrencyDollar, getState: (state) => false },
81
+ ];
82
+
83
+ const Format = () => {
84
+ const { onAction } = useToolbarContext('Format');
85
+ const { t } = useTranslation(SHEET_PLUGIN);
86
+
87
+ return (
88
+ <NaturalToolbar.ToggleGroup
89
+ type='single'
90
+ // value={cellStyles.filter(({ getState }) => state && getState(state)).map(({ type }) => type)}
91
+ >
92
+ {formatOptions.map(({ type, getState, Icon }) => (
93
+ <ToolbarToggleButton
94
+ key={type}
95
+ value={type}
96
+ Icon={Icon}
97
+ // disabled={state?.blockType === 'codeblock'}
98
+ // onClick={state ? () => onAction?.({ type, data: !getState(state) }) : undefined}
99
+ onClick={() => onAction?.({ type })}
100
+ >
101
+ {t(`toolbar ${type} label`)}
102
+ </ToolbarToggleButton>
103
+ ))}
104
+ </NaturalToolbar.ToggleGroup>
105
+ );
106
+ };
107
+
108
+ const alignmentOptions: ButtonProps[] = [
109
+ { type: 'left', Icon: TextAlignLeft, getState: (state) => false },
110
+ { type: 'center', Icon: TextAlignCenter, getState: (state) => false },
111
+ { type: 'right', Icon: TextAlignRight, getState: (state) => false },
112
+ ];
113
+
114
+ const Alignment = () => {
115
+ const { onAction } = useToolbarContext('Alignment');
116
+ const { t } = useTranslation(SHEET_PLUGIN);
117
+
118
+ return (
119
+ <NaturalToolbar.ToggleGroup
120
+ type='single'
121
+ // value={cellStyles.filter(({ getState }) => state && getState(state)).map(({ type }) => type)}
122
+ >
123
+ {alignmentOptions.map(({ type, getState, Icon }) => (
124
+ <ToolbarToggleButton
125
+ key={type}
126
+ value={type}
127
+ Icon={Icon}
128
+ // disabled={state?.blockType === 'codeblock'}
129
+ // onClick={state ? () => onAction?.({ type, data: !getState(state) }) : undefined}
130
+ onClick={() => onAction?.({ type })}
131
+ >
132
+ {t(`toolbar ${type} label`)}
133
+ </ToolbarToggleButton>
134
+ ))}
135
+ </NaturalToolbar.ToggleGroup>
136
+ );
137
+ };
138
+
139
+ const styleOptions: ButtonProps[] = [
140
+ { type: 'clear', Icon: Eraser, getState: (state) => false },
141
+ { type: 'highlight', Icon: HighlighterCircle, getState: (state) => false },
142
+ ];
143
+
144
+ const Styles = () => {
145
+ const { onAction } = useToolbarContext('Alignment');
146
+ const { t } = useTranslation(SHEET_PLUGIN);
147
+
148
+ return (
149
+ <NaturalToolbar.ToggleGroup
150
+ type='single'
151
+ // value={cellStyles.filter(({ getState }) => state && getState(state)).map(({ type }) => type)}
152
+ >
153
+ {styleOptions.map(({ type, getState, Icon }) => (
154
+ <ToolbarToggleButton
155
+ key={type}
156
+ value={type}
157
+ Icon={Icon}
158
+ // disabled={state?.blockType === 'codeblock'}
159
+ // onClick={state ? () => onAction?.({ type, data: !getState(state) }) : undefined}
160
+ onClick={() => onAction?.({ type })}
161
+ >
162
+ {t(`toolbar ${type} label`)}
163
+ </ToolbarToggleButton>
164
+ ))}
165
+ </NaturalToolbar.ToggleGroup>
166
+ );
167
+ };
168
+
169
+ //
170
+ // Actions
171
+ //
172
+
173
+ const Actions = () => {
174
+ // const { onAction } = useToolbarContext('Actions');
175
+ const { t } = useTranslation(SHEET_PLUGIN);
176
+ return (
177
+ <ToolbarButton
178
+ value='comment'
179
+ Icon={ChatText}
180
+ data-testid='editor.toolbar.comment'
181
+ // onClick={() => onAction?.({ type: 'comment' })}
182
+ // disabled={!state || state.comment || !state.selection}
183
+ >
184
+ {t('comment label')}
185
+ </ToolbarButton>
186
+ );
187
+ };
188
+
189
+ export const Toolbar = {
190
+ Root: ToolbarRoot,
191
+ Separator: ToolbarSeparator,
192
+ Alignment,
193
+ Format,
194
+ Styles,
195
+ Actions,
196
+ };
197
+
198
+ export { useToolbarContext };
@@ -0,0 +1,72 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { type Icon } from '@phosphor-icons/react';
6
+ import React from 'react';
7
+
8
+ import {
9
+ Toolbar as NaturalToolbar,
10
+ Tooltip,
11
+ type ToolbarButtonProps as NaturalToolbarButtonProps,
12
+ type ToolbarToggleGroupItemProps as NaturalToolbarToggleGroupItemProps,
13
+ } from '@dxos/react-ui';
14
+ import { getSize } from '@dxos/react-ui-theme';
15
+
16
+ // TODO(burdon): Factor out in common with react-ui-editor.
17
+
18
+ export const iconStyles = getSize(5);
19
+ export const buttonStyles = 'min-bs-0 p-2';
20
+ export const tooltipProps = { side: 'top' as const, classNames: 'z-10' };
21
+
22
+ export const ToolbarSeparator = () => <div role='separator' className='grow' />;
23
+
24
+ //
25
+ // ToolbarButton
26
+ //
27
+
28
+ type ToolbarButtonProps = NaturalToolbarButtonProps & { Icon: Icon };
29
+
30
+ export const ToolbarButton = ({ Icon, children, ...props }: ToolbarButtonProps) => {
31
+ return (
32
+ <Tooltip.Root>
33
+ <Tooltip.Trigger asChild>
34
+ <NaturalToolbar.Button variant='ghost' {...props} classNames={buttonStyles}>
35
+ <Icon className={iconStyles} />
36
+ <span className='sr-only'>{children}</span>
37
+ </NaturalToolbar.Button>
38
+ </Tooltip.Trigger>
39
+ <Tooltip.Portal>
40
+ <Tooltip.Content {...tooltipProps}>
41
+ {children}
42
+ <Tooltip.Arrow />
43
+ </Tooltip.Content>
44
+ </Tooltip.Portal>
45
+ </Tooltip.Root>
46
+ );
47
+ };
48
+
49
+ //
50
+ // ToolbarToggleButton
51
+ //
52
+
53
+ export type ToolbarToggleButtonProps = NaturalToolbarToggleGroupItemProps & { Icon: Icon };
54
+
55
+ export const ToolbarToggleButton = ({ Icon, children, ...props }: ToolbarToggleButtonProps) => {
56
+ return (
57
+ <Tooltip.Root>
58
+ <Tooltip.Trigger asChild>
59
+ <NaturalToolbar.ToggleGroupItem variant='ghost' {...props} classNames={buttonStyles}>
60
+ <Icon className={iconStyles} />
61
+ <span className='sr-only'>{children}</span>
62
+ </NaturalToolbar.ToggleGroupItem>
63
+ </Tooltip.Trigger>
64
+ <Tooltip.Portal>
65
+ <Tooltip.Content {...tooltipProps}>
66
+ {children}
67
+ <Tooltip.Arrow />
68
+ </Tooltip.Content>
69
+ </Tooltip.Portal>
70
+ </Tooltip.Root>
71
+ );
72
+ };
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ export * from './Toolbar';
@@ -0,0 +1,10 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import React from 'react';
6
+
7
+ export * from './ComputeGraph';
8
+
9
+ // Lazily load components for content surfaces.
10
+ export const SheetContainer = React.lazy(() => import('./SheetContainer'));
package/src/index.ts ADDED
@@ -0,0 +1,9 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { SheetPlugin } from './SheetPlugin';
6
+
7
+ export default SheetPlugin;
8
+
9
+ export * from './SheetPlugin';
package/src/meta.tsx ADDED
@@ -0,0 +1,18 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { GridNine, type IconProps } from '@phosphor-icons/react';
6
+ import React from 'react';
7
+
8
+ import { pluginMeta } from '@dxos/app-framework';
9
+
10
+ export const SHEET_PLUGIN = 'dxos.org/plugin/sheet';
11
+
12
+ export default pluginMeta({
13
+ id: SHEET_PLUGIN,
14
+ name: 'Sheet',
15
+ description: 'A simple spreadsheet plugin.',
16
+ iconComponent: (props: IconProps) => <GridNine {...props} />,
17
+ iconSymbol: 'ph--grid-nine--regular',
18
+ });
@@ -0,0 +1,6 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ export * from './model';
6
+ export * from './types';
@@ -0,0 +1,100 @@
1
+ //
2
+ // Copyright 2024 DXOS.org
3
+ //
4
+
5
+ import { expect } from 'chai';
6
+ import { describe, test } from 'vitest';
7
+
8
+ import { SheetModel } from './model';
9
+ import { addressFromA1Notation, rangeFromA1Notation } from './types';
10
+ import { createComputeGraph } from '../components';
11
+ import { createSheet, ValueTypeEnum } from '../types';
12
+
13
+ // TODO(burdon): Test undo (e.g., clear cells).
14
+
15
+ /**
16
+ * VITEST_ENV=chrome p vitest --watch
17
+ * NOTE: Browser test required for hyperformula due to raw translation files.
18
+ */
19
+ describe('model', () => {
20
+ const createModel = async () => {
21
+ const graph = createComputeGraph();
22
+ const sheet = createSheet();
23
+ const model = new SheetModel(graph, sheet, { rows: 5, columns: 5 });
24
+ await model.initialize();
25
+ return model;
26
+ };
27
+
28
+ test('create', async () => {
29
+ const model = await createModel();
30
+ expect(model.bounds).to.deep.eq({ rows: 5, columns: 5 });
31
+ model.setValue(addressFromA1Notation('A1'), 100);
32
+ const value = model.getValue(addressFromA1Notation('A1'));
33
+ expect(value).to.eq(100);
34
+ });
35
+
36
+ test('map formula', async () => {
37
+ const model = await createModel();
38
+ const x1 = model.mapFormulaRefsToIndices('=SUM(A1:A3)');
39
+ const x2 = model.mapFormulaIndicesToRefs(x1);
40
+ expect(x2).to.eq('=SUM(A1:A3)');
41
+ });
42
+
43
+ test('dates', async () => {
44
+ const model = await createModel();
45
+ const cell = addressFromA1Notation('A1');
46
+ model.setValue(cell, '=NOW()');
47
+ const type = model.getValueType(cell);
48
+ expect(type).to.eq(ValueTypeEnum.DateTime);
49
+ const value = model.getValue(cell);
50
+ const date = model.toLocalDate(value as number);
51
+ const now = new Date();
52
+ expect(date.getUTCFullYear()).to.eq(now.getUTCFullYear());
53
+ expect(date.getUTCMonth()).to.eq(now.getUTCMonth());
54
+ expect(date.getUTCDate()).to.eq(now.getUTCDate());
55
+ });
56
+
57
+ test('formula', async () => {
58
+ const model = await createModel();
59
+
60
+ // Nested formula.
61
+ {
62
+ model.setValue(addressFromA1Notation('A1'), 100);
63
+ model.setValue(addressFromA1Notation('A2'), 200);
64
+ model.setValue(addressFromA1Notation('A3'), '=SUM(A1:A2)');
65
+ model.setValue(addressFromA1Notation('A4'), '=SUM(A1:A3)');
66
+ const value = model.getValue(addressFromA1Notation('A4'));
67
+ expect(value).to.eq(600);
68
+ // console.log(JSON.stringify(model.sheet.cells, undefined, 2));
69
+
70
+ const cells = model.getCellValues(rangeFromA1Notation('A1:A4'));
71
+ expect(cells).to.deep.eq([
72
+ [100],
73
+ [200],
74
+ [model.mapFormulaRefsToIndices('=SUM(A1:A2)')],
75
+ [model.mapFormulaRefsToIndices('=SUM(A1:A3)')],
76
+ ]);
77
+ // console.log(JSON.stringify(model.sheet.cells, undefined, 2));
78
+ // console.log(cells);
79
+ }
80
+
81
+ // Insert row.
82
+ {
83
+ model.insertRows(2, 1);
84
+ model.setValue(addressFromA1Notation('A3'), 400);
85
+ const value = model.getValue(addressFromA1Notation('A5'));
86
+ expect(value).to.eq(1000);
87
+
88
+ const cells = model.getCellValues(rangeFromA1Notation('A1:A5'));
89
+ expect(cells).to.deep.eq([
90
+ [100],
91
+ [200],
92
+ [400],
93
+ [model.mapFormulaRefsToIndices('=SUM(A1:A2)')],
94
+ [model.mapFormulaRefsToIndices('=SUM(A1:A4)')],
95
+ ]);
96
+ // console.log(JSON.stringify(model.sheet.cells, undefined, 2));
97
+ // console.log(cells);
98
+ }
99
+ });
100
+ });