rowvia 0.2.4 → 0.3.1

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 (132) hide show
  1. package/README.md +24 -8
  2. package/dist/fields.css +1 -0
  3. package/dist/fields.es.js +1913 -0
  4. package/dist/fields.umd.cjs +1 -0
  5. package/dist/rowvia.css +1 -1
  6. package/dist/rowvia.es.js +12167 -11319
  7. package/dist/rowvia.umd.cjs +93 -104
  8. package/dist/types/api.d.ts +1 -1
  9. package/dist/types/components/cells.d.ts +25 -0
  10. package/dist/types/components/detailDialog.d.ts +7 -1
  11. package/dist/types/components/scrollbars.d.ts +10 -0
  12. package/dist/types/contracts/work-item.d.ts +339 -0
  13. package/dist/types/core/clientSideRowModel.d.ts +1 -2
  14. package/dist/types/core/columnModel.d.ts +2 -2
  15. package/dist/types/core/gridHost.d.ts +365 -0
  16. package/dist/types/core/remoteRowModels.d.ts +2 -10
  17. package/dist/types/core/rowNode.d.ts +1 -2
  18. package/dist/types/core/valueService.d.ts +1 -1
  19. package/dist/types/createGrid.d.ts +10 -0
  20. package/dist/types/features/chartService.d.ts +2 -11
  21. package/dist/types/features/columnMenu.d.ts +1 -1
  22. package/dist/types/features/contextMenu.d.ts +2 -13
  23. package/dist/types/features/editService.d.ts +3 -8
  24. package/dist/types/features/exportService.d.ts +3 -2
  25. package/dist/types/features/filterGui.d.ts +1 -1
  26. package/dist/types/features/filterService.d.ts +2 -14
  27. package/dist/types/features/findService.d.ts +1 -1
  28. package/dist/types/features/formulaEditor.d.ts +1 -1
  29. package/dist/types/features/notesService.d.ts +1 -5
  30. package/dist/types/features/overlays.d.ts +1 -1
  31. package/dist/types/features/paginationService.d.ts +1 -2
  32. package/dist/types/features/popupService.d.ts +1 -1
  33. package/dist/types/features/rangeSelection.d.ts +1 -8
  34. package/dist/types/features/rowDragService.d.ts +1 -1
  35. package/dist/types/features/rowGroupPanel.d.ts +1 -1
  36. package/dist/types/features/selectionService.d.ts +1 -1
  37. package/dist/types/features/sideBar.d.ts +2 -5
  38. package/dist/types/features/sortService.d.ts +1 -1
  39. package/dist/types/features/statusBar.d.ts +2 -3
  40. package/dist/types/features/undoRedoService.d.ts +2 -9
  41. package/dist/types/fields/attachment-control.d.ts +2 -0
  42. package/dist/types/fields/base-field.d.ts +62 -0
  43. package/dist/types/{pages/work-items → fields}/cascade-control.d.ts +1 -1
  44. package/dist/types/{pages/work-items → fields}/choice-control.d.ts +2 -3
  45. package/dist/types/fields/composite-control.d.ts +3 -0
  46. package/dist/types/fields/controls.d.ts +19 -0
  47. package/dist/types/{pages/work-items → fields}/date-control.d.ts +1 -1
  48. package/dist/types/fields/field-types.d.ts +114 -0
  49. package/dist/types/fields/index.d.ts +8 -0
  50. package/dist/types/fields/internal/dom.d.ts +1 -0
  51. package/dist/types/fields/internal/focus-boundary.d.ts +7 -0
  52. package/dist/types/fields/internal/interaction.d.ts +23 -0
  53. package/dist/types/fields/internal/lifecycle.d.ts +12 -0
  54. package/dist/types/fields/internal/textarea.d.ts +1 -0
  55. package/dist/types/fields/location-control.d.ts +3 -0
  56. package/dist/types/fields/popup.d.ts +38 -0
  57. package/dist/types/{pages/work-items → fields}/rich-control.d.ts +1 -1
  58. package/dist/types/fields/text-control.d.ts +3 -0
  59. package/dist/types/fields/types.d.ts +185 -0
  60. package/dist/types/fields/value-control.d.ts +12 -0
  61. package/dist/types/fields/vote-control.d.ts +2 -0
  62. package/dist/types/forms/form-conditions.d.ts +29 -0
  63. package/dist/types/forms/form-surface.d.ts +13 -0
  64. package/dist/types/gantt/component.d.ts +5 -4
  65. package/dist/types/gantt/ganttChart.d.ts +7 -7
  66. package/dist/types/gantt/index.d.ts +3 -3
  67. package/dist/types/gantt/scale.d.ts +18 -0
  68. package/dist/types/grid.d.ts +21 -17
  69. package/dist/types/index.d.ts +21 -20
  70. package/dist/types/node-flow/canvas.d.ts +26 -0
  71. package/dist/types/node-flow/card.d.ts +23 -0
  72. package/dist/types/node-flow/cardSections.d.ts +14 -0
  73. package/dist/types/node-flow/component.d.ts +9 -0
  74. package/dist/types/node-flow/contextBar.d.ts +20 -0
  75. package/dist/types/node-flow/demo.d.ts +6 -0
  76. package/dist/types/node-flow/index.d.ts +13 -0
  77. package/dist/types/node-flow/model.d.ts +48 -0
  78. package/dist/types/node-flow/timeline.d.ts +16 -0
  79. package/dist/types/node-flow/types.d.ts +220 -0
  80. package/dist/types/personnel/component.d.ts +3 -2
  81. package/dist/types/personnel/index.d.ts +1 -1
  82. package/dist/types/personnel/render.d.ts +22 -0
  83. package/dist/types/render/headerView.d.ts +1 -1
  84. package/dist/types/render/rowComponent.d.ts +29 -0
  85. package/dist/types/render/rowContext.d.ts +39 -0
  86. package/dist/types/render/rowRenderer.d.ts +6 -73
  87. package/dist/types/shared/dom.d.ts +1 -0
  88. package/dist/types/shared/interaction.d.ts +1 -0
  89. package/dist/types/shared/lifecycle.d.ts +1 -0
  90. package/dist/types/shared/markup.d.ts +5 -0
  91. package/dist/types/shared/state.d.ts +5 -0
  92. package/dist/types/types.d.ts +3 -2
  93. package/dist/types/work-items/action-surface.d.ts +17 -0
  94. package/dist/types/work-items/detail/detail-comments.d.ts +44 -0
  95. package/dist/types/work-items/detail/detail-header.d.ts +23 -0
  96. package/dist/types/work-items/detail/detail-history.d.ts +38 -0
  97. package/dist/types/work-items/detail/history-model.d.ts +48 -0
  98. package/dist/types/work-items/fields/control-base.d.ts +17 -0
  99. package/dist/types/{pages/work-items → work-items/fields}/focus-editor.d.ts +1 -1
  100. package/dist/types/work-items/fields/registry.d.ts +5 -0
  101. package/dist/types/work-items/index.d.ts +27 -0
  102. package/dist/types/work-items/layers.d.ts +19 -0
  103. package/dist/types/work-items/model.d.ts +10 -0
  104. package/dist/types/work-items/selection-bar.d.ts +7 -0
  105. package/dist/types/work-items/style-scope.d.ts +1 -0
  106. package/dist/types/work-items/table/column-panels.d.ts +39 -0
  107. package/dist/types/work-items/table/columns.d.ts +28 -0
  108. package/dist/types/work-items/table/headers.d.ts +10 -0
  109. package/dist/types/work-items/table/table.d.ts +10 -0
  110. package/dist/types/work-items/tabs.d.ts +14 -0
  111. package/dist/types/work-items/toolbar.d.ts +11 -0
  112. package/dist/types/work-items/views/rule-panels.d.ts +28 -0
  113. package/dist/types/work-items/workflow-detail-model.d.ts +51 -0
  114. package/dist/types/work-items/workflow-detail-types.d.ts +95 -0
  115. package/dist/types/work-items/workflow-detail.d.ts +3 -0
  116. package/package.json +24 -6
  117. package/dist/types/pages/finance/component.d.ts +0 -2
  118. package/dist/types/pages/finance/data.d.ts +0 -14
  119. package/dist/types/pages/hr/component.d.ts +0 -2
  120. package/dist/types/pages/hr/data.d.ts +0 -21
  121. package/dist/types/pages/index.d.ts +0 -13
  122. package/dist/types/pages/inventory/component.d.ts +0 -2
  123. package/dist/types/pages/inventory/data.d.ts +0 -26
  124. package/dist/types/pages/lifecycle.d.ts +0 -24
  125. package/dist/types/pages/performance/component.d.ts +0 -2
  126. package/dist/types/pages/performance/data.d.ts +0 -33
  127. package/dist/types/pages/server-side/component.d.ts +0 -2
  128. package/dist/types/pages/work-items/config.d.ts +0 -118
  129. package/dist/types/pages/work-items/controls.d.ts +0 -50
  130. package/dist/types/pages/work-items/field-controls.d.ts +0 -4
  131. package/dist/types/pages/work-items/model.d.ts +0 -72
  132. package/dist/types/pages/work-items/page.d.ts +0 -24
@@ -1,8 +1,5 @@
1
- import type { Grid } from '../grid';
2
- export interface ToolPanelDef {
3
- id: string;
4
- label: string;
5
- }
1
+ export type { ToolPanelDef } from '../core/gridHost';
2
+ import type { GridHost as Grid } from '../core/gridHost';
6
3
  export declare class SideBarService {
7
4
  private grid;
8
5
  private eBar;
@@ -1,5 +1,5 @@
1
+ import type { GridHost as Grid } from '../core/gridHost';
1
2
  import type { Column, SortDirection, SortModelItem } from '../types';
2
- import type { Grid } from '../grid';
3
3
  export declare class SortService {
4
4
  private grid;
5
5
  constructor(grid: Grid);
@@ -1,11 +1,10 @@
1
- import type { Grid } from '../grid';
2
1
  import type { EventService } from '../core/eventService';
2
+ import type { GridHost as Grid } from '../core/gridHost';
3
3
  export declare class StatusBarService {
4
4
  private grid;
5
- private eventService;
6
5
  private eBar;
7
6
  private panels;
8
- constructor(grid: Grid, eventService: EventService);
7
+ constructor(grid: Grid, _eventService: EventService);
9
8
  getElement(): HTMLElement;
10
9
  isVisible(): boolean;
11
10
  setVisible(visible: boolean): void;
@@ -1,13 +1,6 @@
1
- import type { Grid } from '../grid';
1
+ export type { UndoRedoAction } from '../core/gridHost';
2
2
  import type { EventService } from '../core/eventService';
3
- export interface UndoRedoAction {
4
- rowNodeId: string;
5
- colId: string;
6
- oldValue: any;
7
- newValue: any;
8
- /** batch id — edits committed in one batch share an id and undo together */
9
- batchId: number;
10
- }
3
+ import type { GridHost as Grid, UndoRedoAction } from '../core/gridHost';
11
4
  /**
12
5
  * Undo / Redo for cell edits (ag-grid undoRedoCellEditing).
13
6
  * Records every committed edit and can replay them in both directions.
@@ -0,0 +1,2 @@
1
+ import type { ControlContext, ControlEditor } from './types';
2
+ export declare function attachmentEditor(c: ControlContext): ControlEditor;
@@ -0,0 +1,62 @@
1
+ import type { ControlContext, ControlEditor, FieldContent, FieldEvent, FieldListener, FieldOptions, FieldSnapshot, FieldState, FieldView } from './types';
2
+ import { observeInteractions } from './internal/interaction';
3
+ /** A field owns its value, three states and resources; hosts own persistence. */
4
+ export declare abstract class BaseField {
5
+ private root?;
6
+ private destroying;
7
+ private feedback?;
8
+ protected options: FieldOptions;
9
+ private value;
10
+ private committedValue;
11
+ private state;
12
+ private view?;
13
+ private viewLife;
14
+ private readonly life;
15
+ private readonly listeners;
16
+ private interactions?;
17
+ private readonly interactionListeners;
18
+ private mounted;
19
+ private handled;
20
+ constructor(options: FieldOptions);
21
+ get element(): HTMLElement;
22
+ private bindRoot;
23
+ protected abstract renderDisplay(context: ControlContext): FieldView;
24
+ protected abstract renderEditing(context: ControlContext): ControlEditor;
25
+ protected renderHover(context: ControlContext): FieldView;
26
+ protected beforeInput(value: unknown): unknown;
27
+ protected beforeCommit(_event: FieldEvent): boolean;
28
+ protected beforeCancel(_event: FieldEvent): boolean;
29
+ protected beforeStateChange(_event: FieldEvent): boolean;
30
+ protected validateValue(_value: unknown): string | undefined;
31
+ protected isReadonly(): boolean;
32
+ protected onOutput(_event: FieldEvent): void;
33
+ get snapshot(): FieldSnapshot;
34
+ mount(container?: HTMLElement): this;
35
+ read(): unknown;
36
+ on(listener: FieldListener): () => void;
37
+ onInteraction(listener: Parameters<ReturnType<typeof observeInteractions>['onInteraction']>[0]): () => void;
38
+ input(value: unknown, source?: 'api' | 'user', originalEvent?: Event): void;
39
+ /** External synchronization is distinct from user input; it resets the draft. */
40
+ setValue(value: unknown): void;
41
+ update(options: Partial<FieldOptions>): void;
42
+ validate(): string | undefined;
43
+ commit(source?: 'api' | 'user'): boolean;
44
+ cancel(source?: 'api' | 'user'): void;
45
+ edit(source?: 'api' | 'user'): void;
46
+ setState(state: FieldState, source?: 'api' | 'user'): void;
47
+ action(type: string, value?: unknown): void;
48
+ destroy(): void;
49
+ /** Compatibility hosts can mount an input directly while sharing hooks/events. */
50
+ createEditor(): ControlEditor;
51
+ /** Static view resources belong to the returned handle, with no editing boundary. */
52
+ render(): FieldView;
53
+ private context;
54
+ private showValidation;
55
+ private draw;
56
+ private watch;
57
+ private disposeView;
58
+ private event;
59
+ private emit;
60
+ private publish;
61
+ }
62
+ export declare function renderContent(content: FieldContent): FieldView;
@@ -1,3 +1,3 @@
1
- import type { ControlContext, ControlEditor } from './controls';
1
+ import type { ControlContext, ControlEditor } from './types';
2
2
  export declare function renderCascade(c: ControlContext): HTMLDivElement;
3
3
  export declare function cascadeEditor(multiple: boolean, c: ControlContext): ControlEditor;
@@ -1,6 +1,5 @@
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];
1
+ import type { ControlContext, ControlEditor, FieldConfig, FieldOption } from './types';
2
+ export { element as el } from './internal/dom';
4
3
  export declare const choices: (field: FieldConfig) => FieldOption[];
5
4
  export declare const color: (field: FieldConfig, id: string) => string;
6
5
  export declare function optionLabel(field: FieldConfig, id: string): string;
@@ -0,0 +1,3 @@
1
+ import type { ControlContext, ControlEditor, FieldConfig, FieldControl } from './types';
2
+ /** Row objects are stable identities: adding/removing siblings never remounts an input. */
3
+ export declare function compositeEditor(context: ControlContext, resolve: (field: FieldConfig) => FieldControl): ControlEditor;
@@ -0,0 +1,19 @@
1
+ import { BaseField } from './base-field';
2
+ import type { ControlContext, ControlEditor, FieldConfig, FieldControl, FieldOptions, FieldView } from './types';
3
+ export interface FieldDefinition extends Omit<FieldControl, 'render' | 'renderView' | 'createEditor'> {
4
+ create(options: FieldOptions): BaseField;
5
+ }
6
+ /** Composition root: subclasses never import this registry. */
7
+ export declare function createFieldRegistry(custom?: FieldDefinition[]): {
8
+ register: (definition: FieldDefinition) => void;
9
+ resolve: (field: Pick<FieldConfig, "control" | "kind">) => FieldDefinition;
10
+ create: (options: FieldOptions) => BaseField;
11
+ list: () => FieldDefinition[];
12
+ };
13
+ /** Adapts caller-defined render functions without adding any domain dependency. */
14
+ export declare class CustomField extends BaseField {
15
+ private readonly control;
16
+ constructor(options: FieldOptions, control: Pick<FieldControl, 'render' | 'createEditor'>);
17
+ protected renderDisplay(context: ControlContext): FieldView;
18
+ protected renderEditing(context: ControlContext): ControlEditor;
19
+ }
@@ -1,3 +1,3 @@
1
- import type { ControlContext, ControlEditor } from './controls';
1
+ import type { ControlContext, ControlEditor } from './types';
2
2
  export declare function renderDate(context: ControlContext): HTMLElement;
3
3
  export declare function dateEditor(context: ControlContext): ControlEditor;
@@ -0,0 +1,114 @@
1
+ import { BaseField } from './base-field';
2
+ import type { ControlContext, ControlEditor, FieldConfig, FieldControl, FieldOptions, FieldView } from './types';
3
+ export declare class TextField extends BaseField {
4
+ protected renderDisplay(context: ControlContext): FieldView;
5
+ protected renderEditing(context: ControlContext): ControlEditor;
6
+ }
7
+ export declare class NumberField extends TextField {
8
+ protected renderDisplay(context: ControlContext): FieldView;
9
+ protected renderEditing(context: ControlContext): ControlEditor;
10
+ }
11
+ export declare class RichTextField extends TextField {
12
+ protected renderDisplay(context: ControlContext): FieldView;
13
+ protected renderEditing(context: ControlContext): ControlEditor;
14
+ }
15
+ export declare class TextareaField extends TextField {
16
+ protected renderDisplay(context: ControlContext): FieldView;
17
+ protected renderEditing(context: ControlContext): ControlEditor;
18
+ }
19
+ export declare class LinkField extends TextField {
20
+ protected renderDisplay(context: ControlContext): FieldView;
21
+ protected renderEditing(context: ControlContext): ControlEditor;
22
+ }
23
+ export declare class EmailField extends TextField {
24
+ protected renderEditing(context: ControlContext): ControlEditor;
25
+ }
26
+ export declare class PhoneField extends TextField {
27
+ protected renderEditing(context: ControlContext): ControlEditor;
28
+ }
29
+ export declare class ChoiceField extends BaseField {
30
+ protected multiple: boolean;
31
+ protected variant: 'choice' | 'person' | 'relation' | 'radio';
32
+ protected renderDisplay(context: ControlContext): FieldView;
33
+ protected renderEditing(context: ControlContext): ControlEditor;
34
+ }
35
+ export declare class MultiChoiceField extends ChoiceField {
36
+ protected multiple: boolean;
37
+ }
38
+ export declare class RadioField extends ChoiceField {
39
+ protected variant: "radio";
40
+ }
41
+ export declare class PersonField extends ChoiceField {
42
+ protected variant: "person";
43
+ }
44
+ export declare class MultiPersonField extends PersonField {
45
+ protected multiple: boolean;
46
+ }
47
+ export declare class RelationField extends ChoiceField {
48
+ protected variant: "relation";
49
+ }
50
+ export declare class MultiRelationField extends RelationField {
51
+ protected multiple: boolean;
52
+ }
53
+ export declare class CascadeField extends BaseField {
54
+ protected multiple: boolean;
55
+ protected renderDisplay(context: ControlContext): FieldView;
56
+ protected renderEditing(context: ControlContext): ControlEditor;
57
+ }
58
+ export declare class MultiCascadeField extends CascadeField {
59
+ protected multiple: boolean;
60
+ }
61
+ export declare class DateTimeField extends BaseField {
62
+ protected normalize(context: ControlContext): ControlContext;
63
+ protected renderDisplay(context: ControlContext): FieldView;
64
+ protected renderEditing(context: ControlContext): ControlEditor;
65
+ }
66
+ export declare class DateField extends DateTimeField {
67
+ protected range: boolean;
68
+ protected normalize(context: ControlContext): ControlContext;
69
+ }
70
+ export declare class DateRangeField extends DateField {
71
+ protected range: boolean;
72
+ }
73
+ export declare class SwitchField extends BaseField {
74
+ protected renderDisplay(context: ControlContext): FieldView;
75
+ protected renderEditing(context: ControlContext): ControlEditor;
76
+ }
77
+ export declare class AttachmentField extends BaseField {
78
+ protected renderDisplay(context: ControlContext): FieldView;
79
+ protected renderEditing(context: ControlContext): ControlEditor;
80
+ }
81
+ export declare class LocationField extends BaseField {
82
+ protected renderDisplay(context: ControlContext): FieldView;
83
+ protected renderEditing(context: ControlContext): ControlEditor;
84
+ }
85
+ export declare class VoteField extends BaseField {
86
+ protected mode: 'attitude' | 'single' | 'multi';
87
+ protected renderDisplay(context: ControlContext): FieldView;
88
+ protected renderEditing(context: ControlContext): ControlEditor;
89
+ }
90
+ export declare class SingleVoteField extends VoteField {
91
+ protected mode: "single";
92
+ }
93
+ export declare class MultiVoteField extends VoteField {
94
+ protected mode: "multi";
95
+ }
96
+ export declare class ComputedField extends BaseField {
97
+ protected isReadonly(): boolean;
98
+ constructor(options: FieldOptions);
99
+ protected renderDisplay(context: ControlContext): FieldView;
100
+ protected renderEditing(context: ControlContext): ControlEditor;
101
+ }
102
+ export declare class SignalField extends ComputedField {
103
+ protected renderDisplay(context: ControlContext): FieldView;
104
+ }
105
+ export declare class ActionField extends TextField {
106
+ protected renderDisplay(context: ControlContext): FieldView;
107
+ }
108
+ /** Resolver is supplied by the composition root; never import the registry here. */
109
+ export declare class CompositeField extends BaseField {
110
+ private readonly resolve;
111
+ constructor(options: FieldOptions, resolve: (field: FieldConfig) => FieldControl);
112
+ protected renderDisplay(context: ControlContext): FieldView;
113
+ protected renderEditing(context: ControlContext): ControlEditor;
114
+ }
@@ -0,0 +1,8 @@
1
+ export { BaseField, renderContent } from './base-field';
2
+ export * from './field-types';
3
+ export { createFieldRegistry, CustomField } from './controls';
4
+ export type { FieldDefinition } from './controls';
5
+ export type * from './types';
6
+ export { openFieldPopup, closeAllFieldPopups } from './popup';
7
+ export type { FieldPopup, FieldPopupOptions } from './popup';
8
+ export { sanitizeRichText } from './rich-control';
@@ -0,0 +1 @@
1
+ export declare function element<K extends keyof HTMLElementTagNameMap>(tag: K, className?: string, text?: string): HTMLElementTagNameMap[K];
@@ -0,0 +1,7 @@
1
+ /** One document listener pair, shared by all mounted editing boundaries. */
2
+ interface Boundary {
3
+ contains(node: Node | null, event: Event): boolean;
4
+ leave(event: Event): void;
5
+ }
6
+ export declare function observeFocusBoundary(document: Document, boundary: Boundary): () => void;
7
+ export {};
@@ -0,0 +1,23 @@
1
+ import { type Dispose } from './lifecycle';
2
+ export interface ComponentInteraction {
3
+ component: string;
4
+ type: string;
5
+ action?: string;
6
+ value?: string;
7
+ checked?: boolean;
8
+ /** Snapshot taken before a handler can replace the originating DOM. */
9
+ data: Readonly<Record<string, string>>;
10
+ originalEvent: Event;
11
+ }
12
+ export interface InteractionOptions {
13
+ onInteraction?: (event: ComponentInteraction) => void;
14
+ }
15
+ export interface InteractionSource {
16
+ onInteraction(listener: (event: ComponentInteraction) => void): Dispose;
17
+ }
18
+ /** Complements semantic callbacks with a common, non-cancelling UI event boundary. */
19
+ export declare function observeInteractions(root: HTMLElement, component: string, options?: InteractionOptions, extraRoots?: HTMLElement[]): {
20
+ addRoot: (surface: HTMLElement) => Dispose;
21
+ onInteraction(listener: (event: ComponentInteraction) => void): Dispose;
22
+ destroy(): void;
23
+ };
@@ -0,0 +1,12 @@
1
+ export type Dispose = () => void;
2
+ /** Owns resources for one mounted instance. Disposal is safe to repeat. */
3
+ export declare class Lifecycle {
4
+ private cleanups;
5
+ private stopped;
6
+ get destroyed(): boolean;
7
+ add(cleanup: Dispose): Dispose;
8
+ listen(target: EventTarget, type: string, listener: EventListener, options?: AddEventListenerOptions | boolean): Dispose;
9
+ timeout(callback: () => void, delay: number): number;
10
+ interval(callback: () => void, delay: number): number;
11
+ destroy(): void;
12
+ }
@@ -0,0 +1 @@
1
+ export declare function autosizeTextarea(node: HTMLTextAreaElement, max?: number): () => void;
@@ -0,0 +1,3 @@
1
+ import type { ControlContext, ControlEditor } from './types';
2
+ export declare function locationEditor(c: ControlContext): ControlEditor;
3
+ export declare function renderLocation(c: ControlContext): HTMLDivElement;
@@ -0,0 +1,38 @@
1
+ /**
2
+ * Top-layer popup host for field controls.
3
+ *
4
+ * Feishu Project renders option lists, calendars and cascade columns in a
5
+ * body-level layer that floats above the page: it never joins the document
6
+ * flow, never changes the geometry of the field that opened it and always
7
+ * paints above the drawer/table below it. Rowvia reproduces that contract
8
+ * here so every control shares one anchor/flip/clamp implementation.
9
+ */
10
+ export interface FieldPopupOptions {
11
+ /** Element the popup is anchored to; normally the field trigger box. */
12
+ anchor: HTMLElement;
13
+ /** Use the exact trigger for toolbar menus instead of the containing field. */
14
+ anchorMode?: 'element' | 'field';
15
+ /** Popup content, kept out of the field's DOM subtree. */
16
+ content: HTMLElement;
17
+ /** 'anchor' matches the trigger width, 'auto' hugs the content, a number sets px. */
18
+ width?: 'anchor' | 'auto' | number;
19
+ /** Vertical gap between trigger and popup; Feishu uses 4px. */
20
+ gap?: number;
21
+ /** Align wide date-range panels with the trigger's trailing edge. */
22
+ align?: 'start' | 'end';
23
+ /** Called once whenever the popup closes, including outside clicks and Esc. */
24
+ onDismiss?: () => void;
25
+ /** Override Escape's default field-collapse behavior after closing the popup. */
26
+ onEscape?: () => void;
27
+ }
28
+ export interface FieldPopup {
29
+ /** The body-level layer element carries the independent field style scope. */
30
+ element: HTMLElement;
31
+ reposition: () => void;
32
+ close: () => void;
33
+ }
34
+ /** True when the node belongs to any open field popup (option list, calendar, ...). */
35
+ export declare function isInsideFieldPopup(node: Node | null, owner?: HTMLElement): boolean;
36
+ /** Close every open field popup; hosts call this when a whole surface unmounts. */
37
+ export declare function closeAllFieldPopups(owner?: HTMLElement): void;
38
+ export declare function openFieldPopup(options: FieldPopupOptions): FieldPopup;
@@ -1,4 +1,4 @@
1
- import type { ControlContext, ControlEditor } from './controls';
1
+ import type { ControlContext, ControlEditor } from './types';
2
2
  /** Preserve editor formatting while dropping executable content and untrusted attributes. */
3
3
  export declare function sanitizeRichText(value: unknown): string;
4
4
  export declare function richEditor(context: ControlContext): ControlEditor;
@@ -0,0 +1,3 @@
1
+ import type { ControlContext, ControlEditor } from './types';
2
+ export declare function renderValue(context: ControlContext): HTMLElement;
3
+ export declare function inputEditor(type: string, context: ControlContext): ControlEditor;
@@ -0,0 +1,185 @@
1
+ import type { InteractionOptions, InteractionSource } from './internal/interaction';
2
+ export interface FieldOption {
3
+ id: string;
4
+ label: string;
5
+ color?: string;
6
+ description?: string;
7
+ disabled?: boolean;
8
+ exclusive?: boolean;
9
+ children?: FieldOption[];
10
+ }
11
+ export interface AttachmentValue {
12
+ id: string;
13
+ name: string;
14
+ url?: string;
15
+ size?: number;
16
+ }
17
+ export interface VoteValue {
18
+ selected: string[];
19
+ counts: Record<string, number>;
20
+ total?: number;
21
+ }
22
+ export interface FieldServices {
23
+ searchOptions?: (field: FieldConfig, query: string, signal: AbortSignal) => Promise<FieldOption[]>;
24
+ upload?: (field: FieldConfig, files: File[], signal: AbortSignal) => Promise<AttachmentValue[]>;
25
+ vote?: (field: FieldConfig, selected: string[], signal: AbortSignal) => Promise<VoteValue>;
26
+ }
27
+ export type FieldKind = (string & {}) | "richText" | "number" | "dateTime" | "detail" | "title" | "text" | "longText" | "multiSelect" | "select" | "status" | "person" | "date" | "vote" | "relation";
28
+ export interface FieldConfig {
29
+ key: string;
30
+ label: string;
31
+ kind?: FieldKind;
32
+ /** Registered control ID; defaults to the field kind. */
33
+ control?: string;
34
+ editable?: boolean;
35
+ required?: boolean;
36
+ options?: string[];
37
+ choices?: FieldOption[];
38
+ placeholder?: string;
39
+ maxLength?: number;
40
+ numberOptions?: {
41
+ min?: number;
42
+ max?: number;
43
+ step?: number;
44
+ decimals?: number;
45
+ suffix?: string;
46
+ thousandsSeparator?: boolean;
47
+ };
48
+ attachmentOptions?: {
49
+ accept?: string;
50
+ maxFiles?: number;
51
+ maxBytes?: number;
52
+ };
53
+ compositeFields?: FieldConfig[];
54
+ maxRows?: number;
55
+ /** Maximum selected values for multiSelect; omitted means unlimited. */
56
+ maxSelections?: number;
57
+ /** Calendar features. date hides time by default; dateTime shows it. */
58
+ dateOptions?: {
59
+ showTime?: boolean;
60
+ showRange?: boolean;
61
+ showSeconds?: boolean;
62
+ };
63
+ colors?: Record<string, string>;
64
+ defaultValue?: unknown;
65
+ }
66
+ export interface ControlContext extends InteractionOptions {
67
+ field: FieldConfig;
68
+ /** Opaque caller context; never interpreted by the field runtime. */
69
+ context?: unknown;
70
+ value: unknown;
71
+ layout?: 'compact' | 'form';
72
+ className?: string;
73
+ readonly: boolean;
74
+ /** Permission gate for the expanded and editing states. */
75
+ canEdit?: boolean;
76
+ onAction?: (action: {
77
+ type: string;
78
+ value?: unknown;
79
+ }) => void;
80
+ services?: FieldServices;
81
+ /** Host retains labels for remote selections; values still contain stable IDs only. */
82
+ onSelectedOptions?: (options: FieldOption[]) => void;
83
+ /** Optional host boundary, e.g. a popup containing its Save/Cancel buttons. */
84
+ focusBoundary?: HTMLElement;
85
+ }
86
+ export interface ControlEditor extends Partial<InteractionSource> {
87
+ element: HTMLElement;
88
+ /** Interactive surface hosted outside element, e.g. a top-layer popup.
89
+ * Hosts looking for the editor's inputs must search here too. */
90
+ content?: HTMLElement;
91
+ /** A primitive may bridge portal changes to this single semantic input root. */
92
+ inputRoot?: HTMLElement;
93
+ read: () => unknown;
94
+ validate?: () => string | undefined;
95
+ focus?: () => void;
96
+ destroy?: () => void;
97
+ /** Close internal menus/fullscreen without discarding the draft. */
98
+ deactivate?: () => void;
99
+ }
100
+ export interface FieldControl {
101
+ id: string;
102
+ label: string;
103
+ description: string;
104
+ glyph: string;
105
+ action?: 'edit' | 'select' | 'view';
106
+ group?: '文本' | '选择' | '人员' | '日期' | '投票' | '其他' | '关联工作项' | '系统';
107
+ readonly?: boolean;
108
+ render: (context: ControlContext) => HTMLElement;
109
+ renderView?: (context: ControlContext) => FieldView;
110
+ createEditor: (context: ControlContext) => ControlEditor;
111
+ }
112
+ export type FieldState = 'display' | 'hover' | 'editing';
113
+ /** Explicit content structure; strings are text, never implicit HTML. */
114
+ export type FieldContent = {
115
+ kind: 'text';
116
+ text: string;
117
+ className?: string;
118
+ } | {
119
+ kind: 'node';
120
+ node: HTMLElement;
121
+ destroy?: () => void;
122
+ } | {
123
+ kind: 'group';
124
+ children: FieldContent[];
125
+ className?: string;
126
+ };
127
+ export interface FieldView {
128
+ element: HTMLElement;
129
+ /** Portal content also belongs to this field's input and focus boundary. */
130
+ content?: HTMLElement;
131
+ /** A primitive may bridge portal changes to this single semantic input root. */
132
+ inputRoot?: HTMLElement;
133
+ read?: () => unknown;
134
+ validate?: () => string | undefined;
135
+ focus?: () => void;
136
+ deactivate?: () => void;
137
+ destroy?: () => void;
138
+ }
139
+ export interface FieldSnapshot {
140
+ key: string;
141
+ value: unknown;
142
+ committedValue: unknown;
143
+ state: FieldState;
144
+ readonly: boolean;
145
+ }
146
+ export interface FieldEvent extends FieldSnapshot {
147
+ type: 'input' | 'change' | 'commit' | 'cancel' | 'state' | 'invalid' | 'action' | 'destroy';
148
+ previousValue?: unknown;
149
+ previousState?: FieldState;
150
+ message?: string;
151
+ action?: {
152
+ type: string;
153
+ value?: unknown;
154
+ };
155
+ source: 'api' | 'user';
156
+ originalEvent?: Event;
157
+ }
158
+ export type FieldListener = (event: FieldEvent) => void;
159
+ export interface FieldRenderContext extends FieldSnapshot {
160
+ element: HTMLElement;
161
+ field: Readonly<FieldConfig>;
162
+ content: FieldContent;
163
+ input(value: unknown): void;
164
+ commit(): boolean;
165
+ cancel(): void;
166
+ edit(): void;
167
+ action(type: string, value?: unknown): void;
168
+ /** Render the subclass's default view, optionally wrapping it in a portal. */
169
+ renderDefault(): FieldView;
170
+ }
171
+ export type FieldRenderer = (context: FieldRenderContext) => FieldView;
172
+ export interface FieldOptions extends ControlContext {
173
+ state?: FieldState;
174
+ /** Host-provided display model, recalculated for the current value. */
175
+ content?: FieldContent | ((snapshot: FieldSnapshot) => FieldContent);
176
+ renderers?: Partial<Record<FieldState, FieldRenderer>>;
177
+ hooks?: {
178
+ beforeInput?: (value: unknown, snapshot: FieldSnapshot) => unknown;
179
+ beforeCommit?: (event: FieldEvent) => boolean | void;
180
+ beforeCancel?: (event: FieldEvent) => boolean | void;
181
+ beforeStateChange?: (event: FieldEvent) => boolean | void;
182
+ validate?: (value: unknown) => string | undefined;
183
+ };
184
+ onEvent?: FieldListener;
185
+ }
@@ -0,0 +1,12 @@
1
+ import type { ControlContext, ControlEditor } from './types';
2
+ export declare const text: (v: unknown) => string;
3
+ export declare const emit: (root: HTMLElement) => boolean;
4
+ export declare function safeLink(value: unknown): string | undefined;
5
+ export declare function plain(c: ControlContext): HTMLDivElement;
6
+ export declare function textEditor(c: ControlContext, type: 'textarea' | 'url' | 'email' | 'tel'): ControlEditor;
7
+ export declare function renderLink(c: ControlContext): HTMLDivElement;
8
+ export declare function switchEditor(c: ControlContext): ControlEditor;
9
+ export declare function renderSwitch(c: ControlContext): HTMLElement;
10
+ export declare function renderSignal(c: ControlContext): HTMLDivElement;
11
+ export declare function computedView(c: ControlContext): HTMLDivElement;
12
+ export declare function readonlyEditor(c: ControlContext, render: (c: ControlContext) => HTMLElement): ControlEditor;
@@ -0,0 +1,2 @@
1
+ import type { ControlContext, ControlEditor } from './types';
2
+ export declare function voteEditor(c: ControlContext, mode: 'attitude' | 'single' | 'multi'): ControlEditor;
@@ -0,0 +1,29 @@
1
+ export type FormConditionOp = 'equals' | 'notEqual' | 'contains' | 'notContains' | 'in' | 'notIn' | 'blank' | 'notBlank';
2
+ export interface FormConditionLeaf {
3
+ field: string;
4
+ op: FormConditionOp;
5
+ value?: unknown;
6
+ }
7
+ export type FormCondition = FormConditionLeaf | {
8
+ all: FormCondition[];
9
+ } | {
10
+ any: FormCondition[];
11
+ } | {
12
+ not: FormCondition;
13
+ };
14
+ /** Visibility scope: named members, teams or instance roles (Feishu 可见成员范围). */
15
+ export interface FormScope {
16
+ all?: boolean;
17
+ members?: string[];
18
+ teams?: string[];
19
+ roles?: string[];
20
+ }
21
+ export interface FormSurfaceContext {
22
+ currentUser?: string;
23
+ teams?: string[];
24
+ /** Roles the current member holds on the instance. */
25
+ roles?: string[];
26
+ item?: unknown;
27
+ }
28
+ export declare function evalFormCondition(condition: FormCondition | undefined, data: Record<string, unknown>, context?: FormSurfaceContext): boolean;
29
+ export declare function evalFormScope(scope: FormScope | undefined, context?: FormSurfaceContext): boolean;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Work-item form surface: one component that loads either the create page or
3
+ * the detail page from parameters.
4
+ *
5
+ * Both Feishu surfaces share one form model (fields, layout placements, tabs,
6
+ * conditions, permissions, defaults) and one set of three-state field controls;
7
+ * only the carrier (modal vs drawer), the action bar and the tab chrome differ.
8
+ * See docs/form-surface.md for the parameter model and the tab configuration.
9
+ */
10
+ import type { FormSurfaceConfig, FormSurfaceDeps, FormSurfaceInstance } from '../contracts/work-item';
11
+ export type { FormActionConfig, FormBlockConfig, FormFieldDef, FormFieldPermission, FormGroupConfig, FormLayoutItem, FormPlacement, FormRenderContext, FormSurfaceConfig, FormSurfaceDeps, FormSurfaceEvents, FormSurfaceInstance, FormTabConfig, FormTabKind } from '../contracts/work-item';
12
+ export * from './form-conditions';
13
+ export declare function createWorkItemFormSurface(config: FormSurfaceConfig, deps?: FormSurfaceDeps): FormSurfaceInstance;