rowvia 0.2.3 → 0.2.4

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.
@@ -8,5 +8,6 @@ export { createWorkItemPage } from './work-items/page';
8
8
  export { createControlRegistry, sanitizeRichText } from './work-items/controls';
9
9
  export type { FieldControl, ControlContext, ControlEditor, ControlSurface } from './work-items/controls';
10
10
  export type { WorkItemPageConfig, FieldConfig, FieldKind, FormConfig, FormFieldConfig } from './work-items/config';
11
+ export type { FieldOption, AttachmentValue, VoteValue, FieldServices } from './work-items/config';
11
12
  export type { WorkItem, ViewState, SavedView, Rule, ColorRule } from './work-items/model';
12
13
  export { topicDemoConfig, dateDemoConfig } from './work-items/config';
@@ -0,0 +1,3 @@
1
+ import type { ControlContext, ControlEditor } from './controls';
2
+ export declare function renderCascade(c: ControlContext): HTMLDivElement;
3
+ export declare function cascadeEditor(multiple: boolean, c: ControlContext): ControlEditor;
@@ -0,0 +1,9 @@
1
+ import type { ControlContext, ControlEditor } from './controls';
2
+ import type { FieldConfig, FieldOption } from './config';
3
+ export declare const el: <K extends keyof HTMLElementTagNameMap>(tag: K, cls?: string, text?: string) => HTMLElementTagNameMap[K];
4
+ export declare const choices: (field: FieldConfig) => FieldOption[];
5
+ export declare const color: (field: FieldConfig, id: string) => string;
6
+ export declare function optionLabel(field: FieldConfig, id: string): string;
7
+ export declare function renderChoice(c: ControlContext, variant?: 'choice' | 'person' | 'relation'): HTMLElement;
8
+ /** Shared searchable picker; stores IDs and keeps legacy string options compatible. */
9
+ export declare function choiceEditor(multiple: boolean, c: ControlContext, variant?: 'choice' | 'person' | 'relation' | 'radio'): ControlEditor;
@@ -1,6 +1,33 @@
1
1
  import type { FieldControl } from "./controls";
2
2
  import type { ColDef } from "rowvia";
3
3
  import { type WorkItem } from "./model";
4
+ /** Stable identity is separate from the displayed label. Conditions are resolved by the host. */
5
+ export interface FieldOption {
6
+ id: string;
7
+ label: string;
8
+ color?: string;
9
+ description?: string;
10
+ disabled?: boolean;
11
+ exclusive?: boolean;
12
+ children?: FieldOption[];
13
+ }
14
+ export interface AttachmentValue {
15
+ id: string;
16
+ name: string;
17
+ url?: string;
18
+ size?: number;
19
+ }
20
+ export interface VoteValue {
21
+ selected: string[];
22
+ counts: Record<string, number>;
23
+ total?: number;
24
+ }
25
+ /** The host owns authorization, persistence and idempotency. No network is built into controls. */
26
+ export interface FieldServices {
27
+ searchOptions?: (field: FieldConfig, query: string, signal: AbortSignal) => Promise<FieldOption[]>;
28
+ upload?: (field: FieldConfig, files: File[], signal: AbortSignal) => Promise<AttachmentValue[]>;
29
+ vote?: (field: FieldConfig, item: WorkItem, selected: string[], signal: AbortSignal) => Promise<VoteValue>;
30
+ }
4
31
  export type FieldKind = (string & {}) | "richText" | "number" | "dateTime" | "detail" | "title" | "text" | "longText" | "multiSelect" | "select" | "status" | "person" | "date" | "vote" | "relation";
5
32
  export interface FieldConfig {
6
33
  key: string;
@@ -15,15 +42,34 @@ export interface FieldConfig {
15
42
  editable?: boolean;
16
43
  required?: boolean;
17
44
  options?: string[];
45
+ choices?: FieldOption[];
46
+ placeholder?: string;
47
+ maxLength?: number;
48
+ numberOptions?: {
49
+ min?: number;
50
+ max?: number;
51
+ step?: number;
52
+ decimals?: number;
53
+ suffix?: string;
54
+ thousandsSeparator?: boolean;
55
+ };
56
+ attachmentOptions?: {
57
+ accept?: string;
58
+ maxFiles?: number;
59
+ maxBytes?: number;
60
+ };
61
+ compositeFields?: FieldConfig[];
62
+ maxRows?: number;
18
63
  /** Maximum selected values for multiSelect; omitted means unlimited. */
19
64
  maxSelections?: number;
20
65
  /** Calendar features. date hides time by default; dateTime shows it. */
21
66
  dateOptions?: {
22
67
  showTime?: boolean;
23
68
  showRange?: boolean;
69
+ showSeconds?: boolean;
24
70
  };
25
71
  colors?: Record<string, string>;
26
- defaultValue?: string | number | string[] | null;
72
+ defaultValue?: unknown;
27
73
  column?: Partial<ColDef>;
28
74
  }
29
75
  export interface FormFieldConfig {
@@ -50,6 +96,7 @@ export interface WorkItemPageConfig {
50
96
  detailForm: FormConfig;
51
97
  items: WorkItem[];
52
98
  controls?: FieldControl[];
99
+ fieldServices?: FieldServices;
53
100
  /** Opt in to browser URL hash integration. Disabled for embedded pages. */
54
101
  syncLocationHash?: boolean;
55
102
  onDataChange?: (items: WorkItem[]) => void;
@@ -1,4 +1,5 @@
1
1
  export { sanitizeRichText } from './rich-control';
2
+ import type { FieldServices, FieldOption } from './config';
2
3
  import type { FieldConfig } from './config';
3
4
  import type { WorkItem } from './model';
4
5
  export type ControlSurface = 'cell' | 'detail' | 'create';
@@ -9,6 +10,13 @@ export interface ControlContext {
9
10
  surface: ControlSurface;
10
11
  readonly: boolean;
11
12
  openDetail: (id: string) => void;
13
+ services?: FieldServices;
14
+ /** Host retains labels for remote selections; values still contain stable IDs only. */
15
+ onSelectedOptions?: (options: FieldOption[]) => void;
16
+ /** Transient hosts can dismiss their popup when the editor withdraws. */
17
+ onDeactivate?: () => void;
18
+ /** Optional host boundary, e.g. a popup containing its Save/Cancel buttons. */
19
+ focusBoundary?: HTMLElement;
12
20
  }
13
21
  export interface ControlEditor {
14
22
  element: HTMLElement;
@@ -16,6 +24,8 @@ export interface ControlEditor {
16
24
  validate?: () => string | undefined;
17
25
  focus?: () => void;
18
26
  destroy?: () => void;
27
+ /** Close internal menus/fullscreen without discarding the draft. */
28
+ deactivate?: () => void;
19
29
  }
20
30
  /** Definitions are scoped to a page. Return fresh DOM for each mount. */
21
31
  export interface FieldControl {
@@ -24,6 +34,12 @@ export interface FieldControl {
24
34
  description: string;
25
35
  glyph: string;
26
36
  action?: 'edit' | 'select' | 'view';
37
+ group?: '文本' | '选择' | '人员' | '日期' | '投票' | '其他' | '关联工作项' | '系统';
38
+ readonly?: boolean;
39
+ example?: {
40
+ value: unknown;
41
+ field?: Partial<FieldConfig>;
42
+ };
27
43
  render: (context: ControlContext) => HTMLElement;
28
44
  createEditor: (context: ControlContext) => ControlEditor;
29
45
  }
@@ -0,0 +1,4 @@
1
+ import type { FieldControl } from './controls';
2
+ import type { FieldConfig } from './config';
3
+ export declare function safeLink(value: unknown): string | undefined;
4
+ export declare function extendedControls(resolve: (f: FieldConfig) => FieldControl): FieldControl[];
@@ -0,0 +1,3 @@
1
+ import type { ControlContext, ControlEditor, FieldControl } from './controls';
2
+ /** One focus boundary for every registered editor, including custom controls. */
3
+ export declare function focusEditor(control: FieldControl, context: ControlContext, editor: ControlEditor): ControlEditor;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rowvia",
3
- "version": "0.2.3",
3
+ "version": "0.2.4",
4
4
  "description": "零运行时依赖的 TypeScript 数据表格、甘特图与人员排期组件库",
5
5
  "type": "module",
6
6
  "scripts": {
@@ -10,7 +10,7 @@
10
10
  "build:lib": "vite build --config vite.lib.config.ts && npm run build:types",
11
11
  "preview": "vite preview",
12
12
  "typecheck": "tsc --noEmit",
13
- "test": "esbuild src/index.ts --bundle --format=esm --outfile=dist-test/rowvia.mjs --loader:.ts=ts --log-level=error && node test/smoke.mjs && node test/gantt.mjs && node test/personnel.mjs && node test/work-items.mjs",
13
+ "test": "esbuild src/index.ts --bundle --format=esm --outfile=dist-test/rowvia.mjs --loader:.ts=ts --log-level=error && node test/smoke.mjs && node test/gantt.mjs && node test/personnel.mjs && node test/work-items.mjs && node test/field-controls.mjs",
14
14
  "test:work-items": "node test/work-items.mjs",
15
15
  "build:types": "tsc -p tsconfig.build.json && node scripts/clean-types.mjs",
16
16
  "prepublishOnly": "npm run typecheck && npm test && npm run build:lib && npm run test:pages",