@extable/core 0.1.0 → 0.3.0

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.
@@ -20,6 +20,11 @@ export interface Renderer {
20
20
  element?: HTMLElement;
21
21
  rect: DOMRect;
22
22
  } | null;
23
+ hitTestAction?(event: MouseEvent): {
24
+ rowId: string;
25
+ colKey: string;
26
+ kind: "button" | "link";
27
+ } | null;
23
28
  setActiveCell(rowId: string | null, colKey: string | null): void;
24
29
  setSelection(ranges: SelectionRange[]): void;
25
30
  }
@@ -52,6 +57,11 @@ export declare class HTMLRenderer implements Renderer {
52
57
  element: HTMLElement;
53
58
  rect: DOMRect;
54
59
  } | null;
60
+ hitTestAction(event: MouseEvent): {
61
+ rowId: string;
62
+ colKey: string;
63
+ kind: "button" | "link";
64
+ } | null;
55
65
  private renderHeader;
56
66
  private renderRow;
57
67
  private updateActiveClasses;
@@ -115,6 +125,11 @@ export declare class CanvasRenderer implements Renderer {
115
125
  colKey: null;
116
126
  rect: DOMRect;
117
127
  } | null;
128
+ hitTestAction(event: MouseEvent): {
129
+ rowId: string;
130
+ colKey: string;
131
+ kind: "button" | "link";
132
+ } | null;
118
133
  private isPointInSelection;
119
134
  private handlePointerMove;
120
135
  private handlePointerLeave;
@@ -124,6 +139,9 @@ export declare class CanvasRenderer implements Renderer {
124
139
  private updateCanvasCursor;
125
140
  private measureRowHeight;
126
141
  private wrapLines;
142
+ private fitTextLine;
143
+ private getTextLinesForBounds;
144
+ private measureTextBounds;
127
145
  private drawCellText;
128
146
  private formatValue;
129
147
  }
@@ -1,4 +1,4 @@
1
- import type { Command, EditMode, SelectionRange } from "./types";
1
+ import type { CellAction, Command, EditMode, SelectionRange } from "./types";
2
2
  import type { DataModel } from "./dataModel";
3
3
  type EditHandler = (cmd: Command, commit: boolean) => void;
4
4
  type RowSelectHandler = (rowId: string) => void;
@@ -9,10 +9,16 @@ type HitTest = (event: MouseEvent) => {
9
9
  element?: HTMLElement;
10
10
  rect: DOMRect;
11
11
  } | null;
12
+ type ActionHitTest = (event: MouseEvent) => {
13
+ rowId: string;
14
+ colKey: string;
15
+ kind: "button" | "link";
16
+ } | null;
12
17
  type ActiveChange = (rowId: string | null, colKey: string | null) => void;
13
18
  type ContextMenuHandler = (rowId: string | null, colKey: string | null, clientX: number, clientY: number) => void;
14
19
  type SelectionChange = (ranges: SelectionRange[]) => void;
15
20
  type UndoRedoHandler = () => void;
21
+ type ActionHandler = (action: CellAction) => void;
16
22
  export declare class SelectionManager {
17
23
  private dataModel;
18
24
  private onActiveChange;
@@ -25,6 +31,7 @@ export declare class SelectionManager {
25
31
  private onRowSelect;
26
32
  private onMove;
27
33
  private hitTest;
34
+ private hitAction;
28
35
  private onContextMenu;
29
36
  private handleDocumentContextMenu;
30
37
  private selectionRanges;
@@ -55,8 +62,11 @@ export declare class SelectionManager {
55
62
  private composing;
56
63
  private lastCompositionEnd;
57
64
  private readonly handleSelectionBlur;
65
+ private readonly handleRootKeydown;
58
66
  private isCellReadonly;
59
- constructor(root: HTMLElement, editMode: EditMode, onEdit: EditHandler, onRowSelect: RowSelectHandler, onMove: MoveHandler, hitTest: HitTest, dataModel: DataModel, isCellReadonly: (rowId: string, colKey: string) => boolean, onActiveChange: ActiveChange, onContextMenu: ContextMenuHandler, onSelectionChange: SelectionChange, onUndo: UndoRedoHandler, onRedo: UndoRedoHandler);
67
+ private sequenceLangs?;
68
+ private onCellAction;
69
+ constructor(root: HTMLElement, editMode: EditMode, onEdit: EditHandler, onRowSelect: RowSelectHandler, onMove: MoveHandler, hitTest: HitTest, hitAction: ActionHitTest | null, dataModel: DataModel, sequenceLangs: readonly string[] | undefined, isCellReadonly: (rowId: string, colKey: string) => boolean, onCellAction: ActionHandler, onActiveChange: ActiveChange, onContextMenu: ContextMenuHandler, onSelectionChange: SelectionChange, onUndo: UndoRedoHandler, onRedo: UndoRedoHandler);
60
70
  setEditMode(mode: EditMode): void;
61
71
  syncAfterRowsChanged(): void;
62
72
  navigateToCell(rowId: string, colKey: string): void;
@@ -83,6 +93,7 @@ export declare class SelectionManager {
83
93
  private computeCanvasCellRect;
84
94
  private computeCanvasCellBoxContent;
85
95
  private getCanvasCellMetrics;
96
+ private getActiveCellRect;
86
97
  private ensureVisibleCell;
87
98
  private moveActiveCell;
88
99
  private handlePointerDown;
@@ -119,6 +130,8 @@ export declare class SelectionManager {
119
130
  private autosize;
120
131
  private positionFloatingContentBox;
121
132
  private handleClick;
133
+ private triggerCellAction;
134
+ private openLink;
122
135
  private toggleBoolean;
123
136
  private handleContextMenu;
124
137
  private applySelectionFromHit;
package/dist/types.d.ts CHANGED
@@ -1,12 +1,39 @@
1
1
  export type CellPrimitive = string | number | boolean | null;
2
+ export type ButtonValue = string | {
3
+ label: string;
4
+ command: string;
5
+ commandfor: string;
6
+ };
7
+ export type LinkValue = string | {
8
+ label: string;
9
+ href: string;
10
+ target?: string;
11
+ };
2
12
  export type CellValue = CellPrimitive | Date | {
3
13
  kind: "enum";
4
14
  value: string;
5
15
  } | {
6
16
  kind: "tags";
7
17
  values: string[];
18
+ } | ButtonValue | LinkValue;
19
+ export type ColumnType = "string" | "number" | "boolean" | "datetime" | "date" | "time" | "enum" | "tags" | "button" | "link";
20
+ export type StringFormat = {
21
+ maxLength?: number;
22
+ regex?: string;
23
+ };
24
+ export type NumberFormat = {
25
+ precision?: number;
26
+ scale?: number;
27
+ signed?: boolean;
28
+ thousandSeparator?: boolean;
29
+ negativeRed?: boolean;
30
+ format?: string;
8
31
  };
9
- export type ColumnType = "string" | "number" | "boolean" | "datetime" | "date" | "time" | "enum" | "tags";
32
+ export type BooleanFormat = "checkbox" | string | [string, string];
33
+ export type DateFormat = string;
34
+ export type TimeFormat = string;
35
+ export type DateTimeFormat = string;
36
+ export type ColumnFormat<TType extends ColumnType> = TType extends "string" ? StringFormat : TType extends "number" ? NumberFormat : TType extends "boolean" ? BooleanFormat : TType extends "date" ? DateFormat : TType extends "time" ? TimeFormat : TType extends "datetime" ? DateTimeFormat : never;
10
37
  export type ResolvedCellStyle = {
11
38
  backgroundColor?: string;
12
39
  textColor?: string;
@@ -14,6 +41,8 @@ export type ResolvedCellStyle = {
14
41
  italic?: boolean;
15
42
  underline?: boolean;
16
43
  strike?: boolean;
44
+ readonly?: boolean;
45
+ disabled?: boolean;
17
46
  };
18
47
  export type StyleDelta = Partial<ResolvedCellStyle>;
19
48
  export type DiagnosticLevel = "warning" | "error";
@@ -55,18 +84,7 @@ export interface ColumnSchema<TData extends object = object, RData extends objec
55
84
  */
56
85
  unique?: boolean;
57
86
  nullable?: boolean;
58
- string?: {
59
- maxLength?: number;
60
- regex?: string;
61
- };
62
- number?: {
63
- precision?: number;
64
- scale?: number;
65
- signed?: boolean;
66
- thousandSeparator?: boolean;
67
- negativeRed?: boolean;
68
- format?: string;
69
- };
87
+ format?: ColumnFormat<TType>;
70
88
  enum?: {
71
89
  options: string[];
72
90
  allowCustom?: boolean;
@@ -75,10 +93,6 @@ export interface ColumnSchema<TData extends object = object, RData extends objec
75
93
  options: string[];
76
94
  allowCustom?: boolean;
77
95
  };
78
- booleanDisplay?: "checkbox" | string | [string, string];
79
- dateFormat?: string;
80
- timeFormat?: string;
81
- dateTimeFormat?: string;
82
96
  width?: number;
83
97
  wrapText?: boolean;
84
98
  style?: {
@@ -91,6 +105,8 @@ export interface ColumnSchema<TData extends object = object, RData extends objec
91
105
  bold?: boolean;
92
106
  italic?: boolean;
93
107
  };
108
+ readonly?: boolean;
109
+ disabled?: boolean;
94
110
  };
95
111
  formula?: (data: TData) => unknown;
96
112
  conditionalStyle?: ConditionalStyleFn<RData>;
@@ -163,6 +179,11 @@ export interface Command {
163
179
  next?: unknown;
164
180
  payload?: unknown;
165
181
  }
182
+ export type CommitChanges = {
183
+ commands: Command[];
184
+ user?: UserInfo;
185
+ };
186
+ export type CommitHandler = (changes: CommitChanges) => Promise<void>;
166
187
  export interface UserInfo {
167
188
  id: string;
168
189
  name: string;
@@ -188,32 +209,12 @@ export interface CoreOptions {
188
209
  renderMode?: RenderMode;
189
210
  editMode?: EditMode;
190
211
  lockMode?: LockMode;
191
- /** Loading UI configuration used when `defaultData` is `null`. */
192
- loading?: {
193
- /** Enable built-in loading overlay/spinner. Default: true */
194
- enabled?: boolean;
195
- };
212
+ /** Preferred languages for auto-fill sequence matching (e.g. ["ja", "en"]). */
213
+ langs?: string[];
196
214
  defaultClass?: string | string[];
197
215
  defaultStyle?: Partial<CSSStyleDeclaration>;
198
216
  server?: ServerAdapter;
199
217
  user?: UserInfo;
200
- findReplace?: {
201
- /** Enable Find/Replace feature (engine + integrations). Default: true */
202
- enabled?: boolean;
203
- /**
204
- * Enable the default built-in UI and its shortcut bindings. Default: true
205
- * Note: legacy name is `dialog`; `sidebar` is the preferred name.
206
- */
207
- sidebar?: boolean;
208
- /** @deprecated Use `sidebar` instead. */
209
- dialog?: boolean;
210
- /**
211
- * When true, always intercept `Ctrl/Cmd+F` and show extable's search sidebar.
212
- * Use this when the table is the primary focus of the page and browser Find/Reload should be overridden.
213
- * Default: true (always intercept).
214
- */
215
- enableSearch?: boolean;
216
- };
217
218
  }
218
219
  export interface TableConfig<T extends object = Record<string, unknown>> {
219
220
  data: T[] | null;
@@ -256,6 +257,21 @@ export type TableError = {
256
257
  colKey?: string;
257
258
  };
258
259
  };
260
+ export type ButtonActionValue = {
261
+ label: string;
262
+ command?: undefined;
263
+ commandfor?: undefined;
264
+ } | {
265
+ label: string;
266
+ command: string;
267
+ commandfor: string;
268
+ };
269
+ export type CellAction = {
270
+ kind: "button";
271
+ rowId: string;
272
+ colKey: string;
273
+ value: ButtonActionValue;
274
+ };
259
275
  export type TableState = {
260
276
  canCommit: boolean;
261
277
  pendingCommandCount: number;
@@ -265,9 +281,6 @@ export type TableState = {
265
281
  canRedo: boolean;
266
282
  };
267
283
  renderMode: "html" | "canvas";
268
- ui: {
269
- searchPanelOpen: boolean;
270
- };
271
284
  activeErrors: TableError[];
272
285
  };
273
286
  export type TableStateListener = (next: TableState, prev: TableState | null) => void;
@@ -290,11 +303,12 @@ export type SelectionSnapshot = {
290
303
  activeValueDisplay: string;
291
304
  activeValueType: ColumnType | null;
292
305
  diagnostic: CellDiagnostic | null;
306
+ action?: CellAction | null;
293
307
  styles: {
294
308
  columnStyle: Partial<ResolvedCellStyle>;
295
309
  cellStyle: Partial<ResolvedCellStyle>;
296
310
  resolved: Partial<ResolvedCellStyle>;
297
311
  };
298
312
  };
299
- export type SelectionChangeReason = "selection" | "edit" | "style" | "schema" | "view" | "data" | "unknown";
313
+ export type SelectionChangeReason = "selection" | "edit" | "action" | "style" | "schema" | "view" | "data" | "unknown";
300
314
  export type SelectionListener = (next: SelectionSnapshot, prev: SelectionSnapshot | null, reason: SelectionChangeReason) => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@extable/core",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -23,11 +23,16 @@
23
23
  "./dist/index.css"
24
24
  ],
25
25
  "scripts": {
26
+ "prebuild": "npm run build --workspace @extable/sequence",
27
+ "pretest": "npm run build --workspace @extable/sequence",
26
28
  "build": "tsc -p tsconfig.build.json --emitDeclarationOnly && vite build",
27
29
  "test": "vitest run",
28
30
  "lint": "biome lint .",
29
31
  "format": "biome format --write ."
30
32
  },
33
+ "dependencies": {
34
+ "@extable/sequence": "0.2.0"
35
+ },
31
36
  "devDependencies": {
32
37
  "typescript": "^5.6.3"
33
38
  },
@@ -38,6 +43,7 @@
38
43
  "type": "git",
39
44
  "url": "git+https://github.com/shibukawa/extable.git"
40
45
  },
46
+ "homepage": "https://shibukawa.github.io/extable/",
41
47
  "author": "Yoshiki Shibukawa",
42
48
  "license": "Apache-2.0",
43
49
  "peerDependencies": {}