@extable/core 0.2.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;
@@ -58,7 +65,8 @@ export declare class SelectionManager {
58
65
  private readonly handleRootKeydown;
59
66
  private isCellReadonly;
60
67
  private sequenceLangs?;
61
- constructor(root: HTMLElement, editMode: EditMode, onEdit: EditHandler, onRowSelect: RowSelectHandler, onMove: MoveHandler, hitTest: HitTest, dataModel: DataModel, sequenceLangs: readonly string[] | undefined, isCellReadonly: (rowId: string, colKey: string) => boolean, onActiveChange: ActiveChange, onContextMenu: ContextMenuHandler, onSelectionChange: SelectionChange, onUndo: UndoRedoHandler, onRedo: UndoRedoHandler);
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);
62
70
  setEditMode(mode: EditMode): void;
63
71
  syncAfterRowsChanged(): void;
64
72
  navigateToCell(rowId: string, colKey: string): void;
@@ -122,6 +130,8 @@ export declare class SelectionManager {
122
130
  private autosize;
123
131
  private positionFloatingContentBox;
124
132
  private handleClick;
133
+ private triggerCellAction;
134
+ private openLink;
125
135
  private toggleBoolean;
126
136
  private handleContextMenu;
127
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;
@@ -190,32 +211,10 @@ export interface CoreOptions {
190
211
  lockMode?: LockMode;
191
212
  /** Preferred languages for auto-fill sequence matching (e.g. ["ja", "en"]). */
192
213
  langs?: string[];
193
- /** Loading UI configuration used when `defaultData` is `null`. */
194
- loading?: {
195
- /** Enable built-in loading overlay/spinner. Default: true */
196
- enabled?: boolean;
197
- };
198
214
  defaultClass?: string | string[];
199
215
  defaultStyle?: Partial<CSSStyleDeclaration>;
200
216
  server?: ServerAdapter;
201
217
  user?: UserInfo;
202
- findReplace?: {
203
- /** Enable Find/Replace feature (engine + integrations). Default: true */
204
- enabled?: boolean;
205
- /**
206
- * Enable the default built-in UI and its shortcut bindings. Default: true
207
- * Note: legacy name is `dialog`; `sidebar` is the preferred name.
208
- */
209
- sidebar?: boolean;
210
- /** @deprecated Use `sidebar` instead. */
211
- dialog?: boolean;
212
- /**
213
- * When true, always intercept `Ctrl/Cmd+F` and show extable's search sidebar.
214
- * Use this when the table is the primary focus of the page and browser Find/Reload should be overridden.
215
- * Default: true (always intercept).
216
- */
217
- enableSearch?: boolean;
218
- };
219
218
  }
220
219
  export interface TableConfig<T extends object = Record<string, unknown>> {
221
220
  data: T[] | null;
@@ -258,6 +257,21 @@ export type TableError = {
258
257
  colKey?: string;
259
258
  };
260
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
+ };
261
275
  export type TableState = {
262
276
  canCommit: boolean;
263
277
  pendingCommandCount: number;
@@ -267,9 +281,6 @@ export type TableState = {
267
281
  canRedo: boolean;
268
282
  };
269
283
  renderMode: "html" | "canvas";
270
- ui: {
271
- searchPanelOpen: boolean;
272
- };
273
284
  activeErrors: TableError[];
274
285
  };
275
286
  export type TableStateListener = (next: TableState, prev: TableState | null) => void;
@@ -292,11 +303,12 @@ export type SelectionSnapshot = {
292
303
  activeValueDisplay: string;
293
304
  activeValueType: ColumnType | null;
294
305
  diagnostic: CellDiagnostic | null;
306
+ action?: CellAction | null;
295
307
  styles: {
296
308
  columnStyle: Partial<ResolvedCellStyle>;
297
309
  cellStyle: Partial<ResolvedCellStyle>;
298
310
  resolved: Partial<ResolvedCellStyle>;
299
311
  };
300
312
  };
301
- export type SelectionChangeReason = "selection" | "edit" | "style" | "schema" | "view" | "data" | "unknown";
313
+ export type SelectionChangeReason = "selection" | "edit" | "action" | "style" | "schema" | "view" | "data" | "unknown";
302
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.2.0",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -31,7 +31,7 @@
31
31
  "format": "biome format --write ."
32
32
  },
33
33
  "dependencies": {
34
- "@extable/sequence": "0.1.0"
34
+ "@extable/sequence": "0.2.0"
35
35
  },
36
36
  "devDependencies": {
37
37
  "typescript": "^5.6.3"