@gridify/editors 0.0.0-stage → 1.0.0-rc.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.
- package/LICENSE +163 -0
- package/README.md +140 -2
- package/fesm2022/gridify-editors.mjs +2332 -0
- package/package.json +24 -3
- package/types/gridify-editors.d.ts +1781 -0
|
@@ -0,0 +1,1781 @@
|
|
|
1
|
+
import * as _angular_core from '@angular/core';
|
|
2
|
+
import { Signal, WritableSignal, OnInit } from '@angular/core';
|
|
3
|
+
import * as _gridify_studio from '@gridify/studio';
|
|
4
|
+
import { GfyRibbonTab, GfyProblem, GfyRibbonActionEvent, GfyDockContainerNodeInput, GfyMenu, GfyStatusItem, GfyFormLayoutFile, GfyFormElement, GfyFormPlace, GfyFormLayout } from '@gridify/studio';
|
|
5
|
+
|
|
6
|
+
interface History<T> {
|
|
7
|
+
readonly past: readonly T[];
|
|
8
|
+
readonly present: T;
|
|
9
|
+
readonly future: readonly T[];
|
|
10
|
+
/** What the last change was about; the next change with the same key close in time is joined to it. */
|
|
11
|
+
readonly mergeKey: string | null;
|
|
12
|
+
readonly changedAt: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** A folder or a file in a folder of the project. */
|
|
16
|
+
interface GfyEditorFileEntry {
|
|
17
|
+
/** The name in its folder (no `/`): `main.layout.json`, `layouts`. */
|
|
18
|
+
readonly name: string;
|
|
19
|
+
readonly kind: 'file' | 'folder';
|
|
20
|
+
}
|
|
21
|
+
/** A file of the project as it was read. */
|
|
22
|
+
interface GfyEditorFile {
|
|
23
|
+
readonly text: string;
|
|
24
|
+
/**
|
|
25
|
+
* What tells this content of the file from another one (an ETag of the server, the time of the last change and the size of a file of the computer): the editor gives it back when it saves, so a file
|
|
26
|
+
* that was changed in the meantime is not overwritten without a word. `null`: the place does not know, and a save writes over whatever is there.
|
|
27
|
+
*/
|
|
28
|
+
readonly version: string | null;
|
|
29
|
+
}
|
|
30
|
+
/** The condition of a write. Without one the file is written whatever is there. */
|
|
31
|
+
interface GfyEditorWriteCondition {
|
|
32
|
+
/** The file must be this version (the one that was read or written last): another one, or no file, is a conflict. */
|
|
33
|
+
readonly ifVersion?: string;
|
|
34
|
+
/** There must be no file of this name (Save as… to a new name): one that is there is a conflict. */
|
|
35
|
+
readonly ifAbsent?: boolean;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Where the editors open and save the files of a project. A path is relative to the root of the place, with `/` between the names (`layouts/main.layout.json`); the root folder is `''`. A path that leaves
|
|
39
|
+
* the root (`..`), an empty name and `\` never come from the editors.
|
|
40
|
+
*/
|
|
41
|
+
interface GfyEditorFiles {
|
|
42
|
+
/**
|
|
43
|
+
* What tells this place from the others (without it: the label). A document that was opened from a place belongs to every place with the same id, so a new object for the same place keeps the link
|
|
44
|
+
* of the document (and a document that Auto save brings back after a reload has it again), and another place does not have it: give two places that may have the same label (two folders of the same
|
|
45
|
+
* name) ids of their own.
|
|
46
|
+
*/
|
|
47
|
+
readonly id?: string;
|
|
48
|
+
/** The name of the place, for the dialogs and the status bar: the name of the folder, the address of the server. */
|
|
49
|
+
readonly label: string;
|
|
50
|
+
/** The folders and the files in a folder (`''`: the root). The editor sorts them and shows the files it opens. */
|
|
51
|
+
list(folder: string): Promise<readonly GfyEditorFileEntry[]>;
|
|
52
|
+
/** A file as text, with its version. */
|
|
53
|
+
read(path: string): Promise<GfyEditorFile>;
|
|
54
|
+
/** Writes a file (and makes it when there is none), and gives its new version. A condition that does not hold is refused with `GfyEditorFileConflict`; any other failure is an error of its own. */
|
|
55
|
+
write(path: string, text: string, condition?: GfyEditorWriteCondition): Promise<{
|
|
56
|
+
readonly version: string | null;
|
|
57
|
+
}>;
|
|
58
|
+
}
|
|
59
|
+
/** A write was refused because its condition did not hold: the file was changed (or removed) since it was read, or there is a file already where a new one was to be written. */
|
|
60
|
+
declare class GfyEditorFileConflict extends Error {
|
|
61
|
+
/** The path of the file. */
|
|
62
|
+
readonly path: string;
|
|
63
|
+
readonly name = "GfyEditorFileConflict";
|
|
64
|
+
constructor(
|
|
65
|
+
/** The path of the file. */
|
|
66
|
+
path: string, message?: string);
|
|
67
|
+
}
|
|
68
|
+
interface GfyHttpFilesOptions {
|
|
69
|
+
/**
|
|
70
|
+
* The address of the API, as the server has it: `http://localhost:4300/files`, or a path of the server of the page (`/api/files`). The requests go to `<url>/list` and `<url>/file`; a query of the
|
|
71
|
+
* address (`?project=shop`) goes with every request.
|
|
72
|
+
*/
|
|
73
|
+
readonly url: string;
|
|
74
|
+
/** The name of the place in the editors. Without it: the address. */
|
|
75
|
+
readonly label?: string;
|
|
76
|
+
/** What tells the place from the others (`GfyEditorFiles.id`). Without it: the address. */
|
|
77
|
+
readonly id?: string;
|
|
78
|
+
/** Headers of every request (a token): an object, or a function that gives them for each request. */
|
|
79
|
+
readonly headers?: Readonly<Record<string, string>> | (() => Readonly<Record<string, string>>);
|
|
80
|
+
/** The `credentials` of `fetch`: `'include'` sends the cookies to a server of another origin (one that signs the user in with a cookie). Without it: the cookies of the same origin only. */
|
|
81
|
+
readonly credentials?: RequestCredentials;
|
|
82
|
+
/** The `fetch` that sends the requests (a test, an interceptor of your own). Without it: the `fetch` of the window. */
|
|
83
|
+
readonly fetch?: (input: string, init?: RequestInit) => Promise<Response>;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* The files of a project that a server keeps:
|
|
87
|
+
*
|
|
88
|
+
* - `GET <url>/list?path=<folder>`: the entries of the folder as JSON, `[{"name": "main.layout.json", "kind": "file"}, {"name": "old", "kind": "folder"}]`;
|
|
89
|
+
* - `GET <url>/file?path=<path>`: the text of the file, and its version in the header `ETag`;
|
|
90
|
+
* - `PUT <url>/file?path=<path>`: the text as the body (`text/plain`), with `If-Match: <version>` (the version that was read) or `If-None-Match: *` (a new file); the answer has the new `ETag`, and `412` says
|
|
91
|
+
* that the condition does not hold (a conflict).
|
|
92
|
+
*
|
|
93
|
+
* A server of another origin allows the origin of the page (CORS) with the methods `GET` and `PUT`, the headers `Content-Type`, `If-Match` and `If-None-Match`, and exposes `ETag` (without it the browser
|
|
94
|
+
* hides the version, and the editors write without the check: the console says so once).
|
|
95
|
+
*/
|
|
96
|
+
declare function gfyHttpFiles(options: GfyHttpFilesOptions): GfyEditorFiles;
|
|
97
|
+
/** Can this browser open a folder of the computer (`showDirectoryPicker`: Chrome, Edge and the other browsers of Chromium, on HTTPS or localhost)? */
|
|
98
|
+
declare const gfyLocalFolderSupported: () => boolean;
|
|
99
|
+
/**
|
|
100
|
+
* Asks the user for a folder of the computer, to read and write (the browser asks too). `null`: the user closed the dialog, or chose a folder the browser does not give (a folder of the system). Call it
|
|
101
|
+
* from a click: the browser opens the dialog only for a gesture of the user. `id` lets the browser remember the folder that was chosen last for the next time.
|
|
102
|
+
*/
|
|
103
|
+
declare function gfyPickLocalFolder(id?: string): Promise<FileSystemDirectoryHandle | null>;
|
|
104
|
+
interface GfyLocalFolderOptions {
|
|
105
|
+
/**
|
|
106
|
+
* What tells the folder from the others (`GfyEditorFiles.id`): the browser does not say where a folder is, so two folders of the same name are told apart only by an id that the application gives
|
|
107
|
+
* each folder the user chooses (and keeps with its handle). Without it: the name of the folder.
|
|
108
|
+
*/
|
|
109
|
+
readonly id?: string;
|
|
110
|
+
/** The name of the place in the editors. Without it: the name of the folder. */
|
|
111
|
+
readonly label?: string;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* The files of a folder of the computer, through a handle of the File System Access API (from `gfyPickLocalFolder`, or one that the application kept in IndexedDB). The version of a file is the time of its
|
|
115
|
+
* last change and its size. A handle that was kept has no permission after a reload of the page: the first list, read or write asks the browser for it again, and the browser asks the user (so the first
|
|
116
|
+
* of them comes from a click).
|
|
117
|
+
*/
|
|
118
|
+
declare function gfyLocalFolderFiles(folder: FileSystemDirectoryHandle, options?: GfyLocalFolderOptions): GfyEditorFiles;
|
|
119
|
+
|
|
120
|
+
/** The file of the project the document belongs to. */
|
|
121
|
+
interface ProjectLink {
|
|
122
|
+
/** The id of the place of the file (`GfyEditorFiles.id`, or its label): the link belongs to the place that has it. */
|
|
123
|
+
readonly place: string;
|
|
124
|
+
/** The label of the place, for the status bar. */
|
|
125
|
+
readonly label: string;
|
|
126
|
+
readonly path: string;
|
|
127
|
+
/** The version of the file as it was read or written last (`null`: the place does not know it). */
|
|
128
|
+
readonly version: string | null;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Where a document came from, when it belongs to no file of the project: a new one (`new`), a sample of the editor (`sample`, its label), a file of the computer that was opened or dropped on the editor
|
|
132
|
+
* (`file`, its name: the browser gives no more of it, and cannot write into it), the clipboard (`clipboard`). A document of the project is named by its link instead.
|
|
133
|
+
*/
|
|
134
|
+
type DocumentOrigin = {
|
|
135
|
+
readonly kind: 'new';
|
|
136
|
+
} | {
|
|
137
|
+
readonly kind: 'sample';
|
|
138
|
+
readonly name: string;
|
|
139
|
+
} | {
|
|
140
|
+
readonly kind: 'file';
|
|
141
|
+
readonly name: string;
|
|
142
|
+
} | {
|
|
143
|
+
readonly kind: 'clipboard';
|
|
144
|
+
};
|
|
145
|
+
/** A file that was opened from the project. */
|
|
146
|
+
interface ProjectFile {
|
|
147
|
+
readonly files: GfyEditorFiles;
|
|
148
|
+
readonly path: string;
|
|
149
|
+
readonly text: string;
|
|
150
|
+
readonly version: string | null;
|
|
151
|
+
}
|
|
152
|
+
interface EditorProjectOptions {
|
|
153
|
+
/** What the editor makes, for the titles and the questions: `layout`, `form layout`, `ribbon`. */
|
|
154
|
+
readonly noun: string;
|
|
155
|
+
/** The extension of its files (`.json`): the dialog shows these files, and a name of Save as… ends with it. */
|
|
156
|
+
readonly extension: string;
|
|
157
|
+
/** The prefix of the icons of the editor (its registry has `<prefix>:project-folder` and `<prefix>:project-file`, see `editor-icons.ts`). */
|
|
158
|
+
readonly icons: string;
|
|
159
|
+
/** Where Auto save keeps the link with the text of the document (`remember`, `recall`). */
|
|
160
|
+
readonly storageKey: string;
|
|
161
|
+
/** Writes a message into the status bar of the editor. */
|
|
162
|
+
readonly say: (text: string) => void;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* What the project holds of the document of an editor: the link, where the document came from, whether a save or an opening is on its way, the count of the documents that replaced one another (a save
|
|
166
|
+
* that ends after its document was replaced does not link the new one), and the folder used last. The store leaves it in its keeper with the document, and the store that takes the document back takes it
|
|
167
|
+
* too (`EditorProject.adopt`).
|
|
168
|
+
*/
|
|
169
|
+
declare class ProjectState {
|
|
170
|
+
readonly link: _angular_core.WritableSignal<ProjectLink | null>;
|
|
171
|
+
readonly origin: _angular_core.WritableSignal<DocumentOrigin>;
|
|
172
|
+
readonly busy: _angular_core.WritableSignal<boolean>;
|
|
173
|
+
generation: number;
|
|
174
|
+
lastFolder: string;
|
|
175
|
+
}
|
|
176
|
+
declare class EditorProject {
|
|
177
|
+
private readonly options;
|
|
178
|
+
private readonly dialogs;
|
|
179
|
+
private readonly box;
|
|
180
|
+
private readonly source;
|
|
181
|
+
private readonly current;
|
|
182
|
+
/** The place of the project the application gives the editor now, `null` without one (the File menu is as it always was). */
|
|
183
|
+
readonly files: Signal<GfyEditorFiles | null>;
|
|
184
|
+
/** The link of the document, whatever place it belongs to. */
|
|
185
|
+
readonly link: Signal<ProjectLink | null>;
|
|
186
|
+
/** The link of the document when it belongs to the place the editor has now (a link of another place, or of none, is no link). */
|
|
187
|
+
readonly linked: Signal<ProjectLink | null>;
|
|
188
|
+
/** A save or an opening is on its way: Save or Open pressed again meanwhile does nothing (the status bar says what is on its way). */
|
|
189
|
+
readonly busy: Signal<boolean>;
|
|
190
|
+
/** Where the document came from (what `replaced` was told last): it names a document that has no link. */
|
|
191
|
+
readonly origin: Signal<DocumentOrigin>;
|
|
192
|
+
constructor(options: EditorProjectOptions);
|
|
193
|
+
/** The title of the document for the menu bar of the editor (see `documentTitle`): read it in a `computed`, it follows the link, the origin and the place. */
|
|
194
|
+
title(modified: boolean): DocumentTitle;
|
|
195
|
+
/** Takes the place from the input of the editor (read while it is needed, so a new place counts at once). */
|
|
196
|
+
connect(files: () => GfyEditorFiles | null | undefined): void;
|
|
197
|
+
/** What the project holds of the document, for the keeper of the editor. */
|
|
198
|
+
get state(): ProjectState;
|
|
199
|
+
/** The document came back from the keeper: its project comes with it (a save that is still on its way ends in it). */
|
|
200
|
+
adopt(state: ProjectState): void;
|
|
201
|
+
/**
|
|
202
|
+
* The document was replaced by one that is not a file of the project (yet): it has no link, and it came from `origin`. A file of the project that is opened is replaced first (as a file of the computer,
|
|
203
|
+
* by its path) and linked to it then (`linkTo`).
|
|
204
|
+
*/
|
|
205
|
+
replaced(origin: DocumentOrigin): void;
|
|
206
|
+
/** The document is the file that was opened (after it was loaded). */
|
|
207
|
+
linkTo(file: ProjectFile): void;
|
|
208
|
+
/** The dialog asks for a file of the project, and the file is read: `null` when none was chosen, or it could not be read (the user was told). */
|
|
209
|
+
open(): Promise<ProjectFile | null>;
|
|
210
|
+
/**
|
|
211
|
+
* Writes the text into the file of the link, when the file is still the version that was read (another one is asked about: overwrite it or not). A document without a link asks where it goes
|
|
212
|
+
* (`saveAs`). `true` when the document that is open now was saved, so the editor marks it saved.
|
|
213
|
+
*/
|
|
214
|
+
save(text: string, name: string): Promise<boolean>;
|
|
215
|
+
/** Asks for a folder and a name (the ones of the link, or the folder used last and `name`), and writes the text there; a file that is there is asked about. The document is linked to the new file. */
|
|
216
|
+
saveAs(text: string, name: string): Promise<boolean>;
|
|
217
|
+
private write;
|
|
218
|
+
private mayOverwrite;
|
|
219
|
+
private fail;
|
|
220
|
+
/** The dialog of the files: the path that was chosen, `null` when it was closed without one (Cancel, Esc, the cross). */
|
|
221
|
+
private choose;
|
|
222
|
+
/** Keeps the link (or that there is none) and where the document came from beside the text that Auto save keeps: call it when the text is kept. */
|
|
223
|
+
remember(): void;
|
|
224
|
+
/** Forgets the link that was kept: call it when the text is forgotten. */
|
|
225
|
+
forget(): void;
|
|
226
|
+
/** The link and the origin that were kept with the text come back with it: call it when the text comes back (a link kept before the origin was kept comes back alone). */
|
|
227
|
+
recall(): void;
|
|
228
|
+
}
|
|
229
|
+
/** The title of a document in the menu bar of an editor: the text, and what its tooltip says. */
|
|
230
|
+
interface DocumentTitle {
|
|
231
|
+
readonly text: string;
|
|
232
|
+
readonly tooltip: string;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
interface EditorText {
|
|
236
|
+
/** The text with the values in place of its `{placeholders}`; a placeholder that has no value stays as it is. */
|
|
237
|
+
text(source: string, params?: Readonly<Record<string, string | number>>): string;
|
|
238
|
+
/** The text as a signal, for an input of the docking engine that takes one (the title of a window). */
|
|
239
|
+
signal(source: string): Signal<string>;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
243
|
+
[key: string]: JsonValue;
|
|
244
|
+
};
|
|
245
|
+
type JsonObject = {
|
|
246
|
+
[key: string]: JsonValue;
|
|
247
|
+
};
|
|
248
|
+
/** The way from the root to a value: the names of the properties and the indexes of the arrays (`['tabs', 0, 'sections', 1]`). */
|
|
249
|
+
type JsonPath = readonly (string | number)[];
|
|
250
|
+
/** A place in the text: lines and columns count from 1, the offset from 0. */
|
|
251
|
+
interface JsonPosition {
|
|
252
|
+
line: number;
|
|
253
|
+
column: number;
|
|
254
|
+
offset: number;
|
|
255
|
+
}
|
|
256
|
+
/** What is wrong, as a text with `{placeholders}` (English: the text function of the editor fills the placeholders) and the values for them. */
|
|
257
|
+
interface JsonErrorInfo extends JsonPosition {
|
|
258
|
+
template: string;
|
|
259
|
+
params: Record<string, string | number>;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
/** The cells of an item: 1-based, the spans are numbers. */
|
|
263
|
+
interface Cell {
|
|
264
|
+
col: number;
|
|
265
|
+
row: number;
|
|
266
|
+
colSpan: number;
|
|
267
|
+
rowSpan: number;
|
|
268
|
+
}
|
|
269
|
+
interface PlacedItem extends Cell {
|
|
270
|
+
/** The item sets its column (or covers all columns). */
|
|
271
|
+
colFixed: boolean;
|
|
272
|
+
/** The item sets its row (or covers all rows). */
|
|
273
|
+
rowFixed: boolean;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
/** The inputs of `<gfy-ribbon>` that change how the tabs are drawn. They are not part of the tabs, so they live beside them. */
|
|
277
|
+
interface RibbonOptions {
|
|
278
|
+
defaultRows: number;
|
|
279
|
+
uniformRows: boolean;
|
|
280
|
+
/**
|
|
281
|
+
* The width of every column in px (see `colWidth` of `<gfy-ribbon>`), 24 for a new ribbon; `null` = not set: the ribbon makes every column as wide as its content. The editor always draws the columns
|
|
282
|
+
* at a fixed width, because an item covers as many cells as its `colSpan` says: a ribbon without `colWidth` is drawn with `DRAWN_COL_WIDTH` (see `drawnColWidth`).
|
|
283
|
+
*/
|
|
284
|
+
colWidth: number | null;
|
|
285
|
+
/** The gap between the columns in px (0 is no gap); `null` = the gap of the density. */
|
|
286
|
+
colGap: number | null;
|
|
287
|
+
collapsible: boolean;
|
|
288
|
+
search: boolean;
|
|
289
|
+
/** The text of the empty search box; `null` = the text of the library, `''` = no text. */
|
|
290
|
+
searchPlaceholder: string | null;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
/** What a file says besides the tabs: the options of the element, and the custom functions as the text of the Ribbon Options window (`s.field:2, s.flag:2`). */
|
|
294
|
+
interface FileSettings$1 {
|
|
295
|
+
readonly options: RibbonOptions;
|
|
296
|
+
readonly functions: string;
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
/** What goes with the ribbon besides its tabs, and is a step of undo as well: the options of the element and the custom functions (`s.field:2, s.flag:2`). */
|
|
300
|
+
type Settings$1 = FileSettings$1;
|
|
301
|
+
/** What a step of undo brings back: the ribbon (always a list of tabs), its options and its custom functions. */
|
|
302
|
+
interface Snapshot$1 extends Settings$1 {
|
|
303
|
+
readonly root: JsonValue;
|
|
304
|
+
}
|
|
305
|
+
interface EditorState$2 {
|
|
306
|
+
/** The ribbon with its options and functions, and the steps before and after it. */
|
|
307
|
+
readonly history: History<Snapshot$1>;
|
|
308
|
+
/** What the reading of the file that was loaded let pass although JSON does not (comments, single quotes, a declaration around the list, ...). It is gone with the next change. */
|
|
309
|
+
readonly notes: readonly JsonErrorInfo[];
|
|
310
|
+
/** The tab, section, item or choice that is selected. */
|
|
311
|
+
readonly selected: JsonPath | null;
|
|
312
|
+
/** The snapshot that the file on the disk holds: the one that was loaded, or the one that was downloaded last (`markSaved`). The document is modified while another one is present. */
|
|
313
|
+
readonly saved: Snapshot$1;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
declare const CHOICE_KINDS: readonly ["item", "separator", "header", "source"];
|
|
317
|
+
/** What the menus Add choice add to the choices of an item or a choice (the context menu, the button of the Outline): an entry, a separator, a heading, or a block of menu items. */
|
|
318
|
+
interface ChoiceEntry {
|
|
319
|
+
/** The identity of the entry among the others. */
|
|
320
|
+
id: string;
|
|
321
|
+
label: string;
|
|
322
|
+
description: string;
|
|
323
|
+
kind: (typeof CHOICE_KINDS)[number];
|
|
324
|
+
/** `kind: 'source'`: the name of the block. */
|
|
325
|
+
source?: string;
|
|
326
|
+
}
|
|
327
|
+
type InputKind = 'boolean' | 'integer' | 'number' | 'text' | 'choice' | 'list' | 'function';
|
|
328
|
+
interface InputSpec {
|
|
329
|
+
name: string;
|
|
330
|
+
kind: InputKind;
|
|
331
|
+
/** `choice`: the allowed values. */
|
|
332
|
+
options?: readonly string[];
|
|
333
|
+
/** What the control does while the input is missing. It is shown, and never written. */
|
|
334
|
+
fallback?: JsonValue;
|
|
335
|
+
/** `integer`: the smallest value. */
|
|
336
|
+
min?: number;
|
|
337
|
+
/** `function`: the TypeScript type of the function, for the code that is generated. */
|
|
338
|
+
signature?: string;
|
|
339
|
+
/** `text`: the input holds a CSS color, so the Inspector edits it with a color picker (see `FieldSpec.color`). */
|
|
340
|
+
color?: boolean;
|
|
341
|
+
/**
|
|
342
|
+
* The input does something only while another input of the control has (or has not) a value: the Inspector offers its row then, and while it is written. `equals`: the other input is this (what it is while it is
|
|
343
|
+
* missing is its `fallback`); `not`: it is anything else. An input that is code (a signal) counts as met.
|
|
344
|
+
*/
|
|
345
|
+
dependsOn?: {
|
|
346
|
+
input: string;
|
|
347
|
+
equals?: JsonValue;
|
|
348
|
+
not?: JsonValue;
|
|
349
|
+
};
|
|
350
|
+
description: string;
|
|
351
|
+
}
|
|
352
|
+
type ControlGroup = 'buttons' | 'menus' | 'toggles' | 'fields' | 'display';
|
|
353
|
+
/** Does the control take `choices`: not at all, may have them, or is nothing without them. */
|
|
354
|
+
type ChoicesUse = 'none' | 'optional' | 'required';
|
|
355
|
+
/** What `item.value` is for a control. */
|
|
356
|
+
type ValueKind = 'none' | 'text' | 'number' | 'any';
|
|
357
|
+
/**
|
|
358
|
+
* What a control does with the properties of the choices of its item (read from the controls of the library): a property it does not use is ignored by it, so the Inspector does not offer it. `structure`: a
|
|
359
|
+
* separator, a heading and a block of menu items are interpreted (a menu does; a table picker and a select skip them, a gallery, a combo box and a toggle group would draw them as ordinary entries). `icon`: the icon
|
|
360
|
+
* of the choice is drawn. `tile`: `preview` and `style`, the tile of a gallery. `checked`: the state of a button of a toggle group. `disabled`: the choice can be switched off. `submenu`: the choice may hold `choices`
|
|
361
|
+
* of its own.
|
|
362
|
+
*/
|
|
363
|
+
interface ChoiceUse {
|
|
364
|
+
structure: boolean;
|
|
365
|
+
icon: boolean;
|
|
366
|
+
tile: boolean;
|
|
367
|
+
checked: boolean;
|
|
368
|
+
disabled: boolean;
|
|
369
|
+
submenu: boolean;
|
|
370
|
+
}
|
|
371
|
+
interface ControlSpec {
|
|
372
|
+
type: string;
|
|
373
|
+
label: string;
|
|
374
|
+
group: ControlGroup;
|
|
375
|
+
description: string;
|
|
376
|
+
inputs: readonly InputSpec[];
|
|
377
|
+
choices: ChoicesUse;
|
|
378
|
+
/** Which properties of a choice the control uses (the rows of a choice in the Inspector follow it). */
|
|
379
|
+
choiceUse: ChoiceUse;
|
|
380
|
+
value: ValueKind;
|
|
381
|
+
/** Does the control use `item.checked`? */
|
|
382
|
+
checked: boolean;
|
|
383
|
+
/** Does the control draw the `icon` of the item (and so its `iconColor`)? The Inspector offers the two rows only for a control that does; a gallery and a toggle group draw the icons of their choices. */
|
|
384
|
+
icon: boolean;
|
|
385
|
+
/** Is it a command: it has a KeyTip, is found by the command search and can have a shortcut. */
|
|
386
|
+
command: boolean;
|
|
387
|
+
/** The properties of an item (`ITEM_FIELDS`) that the control does not use: the Inspector does not offer their rows (it keeps one that is written). */
|
|
388
|
+
ignores?: readonly string[];
|
|
389
|
+
/** What the action event carries as `value`, for the comment in the generated code. */
|
|
390
|
+
emits: string;
|
|
391
|
+
/** The number of rows the control spans when the item does not say, from the inputs of the item. */
|
|
392
|
+
defaultRowSpan(inputs: JsonObject): 'all' | 1;
|
|
393
|
+
/** A new item of this control: `id` is its handle, `tr` translates the texts that the user will see. */
|
|
394
|
+
create(id: string, tr: (text: string) => string): JsonObject;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/** The cells that an item is stretched to: what is not given stays as it is. */
|
|
398
|
+
interface StretchSize {
|
|
399
|
+
col?: number;
|
|
400
|
+
row?: number;
|
|
401
|
+
colSpan?: number;
|
|
402
|
+
rowSpan?: number;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
/** A row of the inspector. It has the shape of `GfyProperty` of the property grid. */
|
|
406
|
+
interface InspectorRow$2 {
|
|
407
|
+
id: string;
|
|
408
|
+
/** The name of the property the row writes, as it stands in the JSON or in the component (`showForTags`, the `menuLayout` of `inputs`), not a translation of it: this is a tool for developers. A row that the editor adds is named like its id. */
|
|
409
|
+
label: string;
|
|
410
|
+
/** `readonly`: a value that is shown and cannot be typed (the place of an item, which is worked out from the grid). `color`: a color picker (it writes the code of the color, `#2563eb`; a row that holds code is a text row). */
|
|
411
|
+
kind: 'text' | 'number' | 'boolean' | 'select' | 'color' | 'readonly';
|
|
412
|
+
category: string;
|
|
413
|
+
description: string;
|
|
414
|
+
options?: readonly {
|
|
415
|
+
value: string;
|
|
416
|
+
label: string;
|
|
417
|
+
}[];
|
|
418
|
+
min?: number;
|
|
419
|
+
step?: number;
|
|
420
|
+
decimals?: number;
|
|
421
|
+
placeholder?: string;
|
|
422
|
+
defaultValue?: unknown;
|
|
423
|
+
/** The library takes a signal for the property, and the row is not a text field (a switch, a list, a number, a color): `bindRow` turns it into a code row (`=@name`). */
|
|
424
|
+
bindable?: boolean;
|
|
425
|
+
/** The row is shown and cannot be changed (the kind of a choice): the description says why, and `changeRow` refuses it too. */
|
|
426
|
+
disabled?: boolean;
|
|
427
|
+
/**
|
|
428
|
+
* The property holds code of the application (`{"$expr": "..."}`): the row is a text row that shows the code with a `=` in front (like a formula), and `was` is the kind the row has when the
|
|
429
|
+
* value is not code (a switch, a number, a list...). A text that starts with `=` is code, any other is the plain value of the row.
|
|
430
|
+
*/
|
|
431
|
+
code?: {
|
|
432
|
+
was: 'text' | 'number' | 'boolean' | 'select';
|
|
433
|
+
defaultValue?: unknown;
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
interface Inspector$2 {
|
|
437
|
+
/** What is inspected: a tab, a section, an item or a choice. */
|
|
438
|
+
kind: 'tab' | 'section' | 'item' | 'choice';
|
|
439
|
+
path: JsonPath;
|
|
440
|
+
/** The rows, in the order of the categories. */
|
|
441
|
+
rows: InspectorRow$2[];
|
|
442
|
+
/** The values of the rows, by the id of the row. A property that is not set is missing. */
|
|
443
|
+
values: Record<string, unknown>;
|
|
444
|
+
/** The control of an item (`undefined` for the others, and for a control the editor does not know). */
|
|
445
|
+
control: ControlSpec | undefined;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/** The kinds of text the output window can show. */
|
|
449
|
+
type OutputKind$2 = 'file' | 'json' | 'typescript' | 'handler' | 'template' | 'usage';
|
|
450
|
+
/** A problem of the list: the problem of the list of the library, and the node it is about (a note on the reading of the file is about none). */
|
|
451
|
+
interface EditorProblem$2 extends GfyProblem {
|
|
452
|
+
readonly nodePath: JsonPath | null;
|
|
453
|
+
}
|
|
454
|
+
/** A request of the store to the preview: measure the items and widen those that are too narrow for their content (see `RibbonEditorStore.fitItems`). */
|
|
455
|
+
interface FitRequest {
|
|
456
|
+
/** A new request has a number that is higher than the last one. */
|
|
457
|
+
readonly seq: number;
|
|
458
|
+
/** The items to look at. */
|
|
459
|
+
readonly items: readonly JsonPath[];
|
|
460
|
+
/** The step of undo that the widening joins (the step that added the item), if any. */
|
|
461
|
+
readonly key: string | undefined;
|
|
462
|
+
/** Is the user told what was done? Only when an item was widened (a change of the content of an item), or never (an item that was added). */
|
|
463
|
+
readonly announce: false | 'widened';
|
|
464
|
+
}
|
|
465
|
+
/** An item whose content needs more columns than the item covers, as the preview measured it. */
|
|
466
|
+
interface Overflow {
|
|
467
|
+
readonly path: JsonPath;
|
|
468
|
+
readonly needed: number;
|
|
469
|
+
readonly have: number;
|
|
470
|
+
}
|
|
471
|
+
/** What the commands that need a selected node can do now. */
|
|
472
|
+
interface Capabilities$2 {
|
|
473
|
+
readonly remove: boolean;
|
|
474
|
+
readonly duplicate: boolean;
|
|
475
|
+
readonly moveUp: boolean;
|
|
476
|
+
readonly moveDown: boolean;
|
|
477
|
+
readonly addSection: boolean;
|
|
478
|
+
readonly addChoice: boolean;
|
|
479
|
+
/** A choice may hold choices of its own: the choice of the menu of a split button or a dropdown button, when it is an entry (the choices of the other controls are a flat list). */
|
|
480
|
+
readonly addSubChoice: boolean;
|
|
481
|
+
/** What the toolbox may add to the choices of the selected item, or next to the selected choice: a separator, a heading and a block only where the control interprets them. */
|
|
482
|
+
readonly choiceEntries: readonly ChoiceEntry[];
|
|
483
|
+
}
|
|
484
|
+
declare class RibbonEditorStore {
|
|
485
|
+
private readonly toast;
|
|
486
|
+
private readonly box;
|
|
487
|
+
private readonly icons;
|
|
488
|
+
/** The files of the project, while the application gives the editor a place for them (the input `files` of the editor): File > Open from the project…, Save and Save as…. */
|
|
489
|
+
readonly project: EditorProject;
|
|
490
|
+
/** The editor starts with an empty list of tabs (the samples are in File > Samples); with Auto save on, what was kept in the browser replaces it (see `restore`). */
|
|
491
|
+
readonly state: WritableSignal<EditorState$2>;
|
|
492
|
+
readonly root: _angular_core.Signal<JsonValue>;
|
|
493
|
+
readonly notes: _angular_core.Signal<readonly JsonErrorInfo[]>;
|
|
494
|
+
/** The selected node. A change of the ribbon makes a new path for the node that stays selected: it is the same selection (the windows that follow it are not told). */
|
|
495
|
+
readonly selected: _angular_core.Signal<JsonPath | null>;
|
|
496
|
+
readonly canUndo: _angular_core.Signal<boolean>;
|
|
497
|
+
readonly canRedo: _angular_core.Signal<boolean>;
|
|
498
|
+
/** The document has been changed since it was loaded or downloaded: the tabs, the options or the custom functions (the file holds all of them). */
|
|
499
|
+
readonly modified: _angular_core.Signal<boolean>;
|
|
500
|
+
/** Goes up when another document replaces the one that is edited: a window that keeps something by the place of a node (the open nodes of the Outline) starts again then. */
|
|
501
|
+
readonly documentSeq: WritableSignal<number>;
|
|
502
|
+
/** The options of `<gfy-ribbon>` that are not part of the tabs: they are for the preview and for the template that is generated. They are steps of undo, as the ribbon is (they live in the same history). */
|
|
503
|
+
readonly options: _angular_core.Signal<RibbonOptions>;
|
|
504
|
+
/** The preview shows the grid of cells (for finding the place of an item). */
|
|
505
|
+
readonly showGrid: WritableSignal<boolean>;
|
|
506
|
+
/** The preview draws a faint background over the cells of every item, to see where each one lies (without the grid). */
|
|
507
|
+
readonly showBackground: WritableSignal<boolean>;
|
|
508
|
+
/** The width of the ribbon in the Editor window in px, or `null` for all the room (a narrow ribbon shows how the sections shrink and collapse). */
|
|
509
|
+
readonly previewWidth: WritableSignal<number | null>;
|
|
510
|
+
/** Does the check of the ribbon look for the icons in the registry of this editor? Off by default: the ribbon of an application has icons that this editor does not have. */
|
|
511
|
+
readonly checkIcons: WritableSignal<boolean>;
|
|
512
|
+
/** The custom functions of the file, as the text of the Ribbon Options window (`s.field:2, s.flag:2`): a step of undo like the options. */
|
|
513
|
+
readonly customFunctions: _angular_core.Signal<string>;
|
|
514
|
+
/** The functions an expression may call: the predefined ones and the custom ones, and the argument of each that holds the text the preview shows (see `core/ribbon-expression.ts`). */
|
|
515
|
+
readonly functions: _angular_core.Signal<Map<string, number>>;
|
|
516
|
+
readonly predefinedFunctions: string;
|
|
517
|
+
/** The whole file as text: the custom functions, the options and the tabs. */
|
|
518
|
+
readonly file: _angular_core.Signal<string>;
|
|
519
|
+
/** What the preview is asked to do next: widen the items to the cells their content needs. A request is carried out once; the preview remembers the number of the last one it did. */
|
|
520
|
+
readonly fitRequest: WritableSignal<FitRequest | null>;
|
|
521
|
+
private fitSeq;
|
|
522
|
+
/** The items of the tab that is shown whose content is wider than their cells (the preview measures them after every change, and the list of problems tells). */
|
|
523
|
+
readonly overflows: WritableSignal<readonly Overflow[]>;
|
|
524
|
+
/** The control that is being dragged from the toolbox (the preview draws the cells it would cover); `null` when nothing is. */
|
|
525
|
+
readonly dragType: WritableSignal<string | null>;
|
|
526
|
+
readonly outputKind: WritableSignal<OutputKind$2>;
|
|
527
|
+
readonly status: WritableSignal<string>;
|
|
528
|
+
/** File > Auto save: the file is kept in the browser while it is edited and comes back at the next visit. Off by default, and a setting of the editor (not part of the document, not a step of undo). */
|
|
529
|
+
readonly autoSave: WritableSignal<boolean>;
|
|
530
|
+
constructor();
|
|
531
|
+
/** The state that an editor of this application left when it was closed (see `RibbonEditorKeeper`). */
|
|
532
|
+
private takeBack;
|
|
533
|
+
/** Turns Auto save on or off. Off: what was kept of the document goes at once. On: the document is kept from now on. */
|
|
534
|
+
setAutoSave(on: boolean): void;
|
|
535
|
+
private readAutoSave;
|
|
536
|
+
/** Takes away what an older version of the editor kept in the browser (see `LEGACY_KEYS`). */
|
|
537
|
+
private forgetLegacy;
|
|
538
|
+
/**
|
|
539
|
+
* The file that was kept (Auto save on) replaces the empty ribbon; one that was not saved after its last change comes back with its changes not saved, and with the file of the project it belongs to.
|
|
540
|
+
* A text that cannot be read is not loaded: the editor starts with the empty ribbon, and the next save of Auto save writes over the text. Gives whether a file came back.
|
|
541
|
+
*/
|
|
542
|
+
private restore;
|
|
543
|
+
/** The editor has nothing but the empty ribbon it started with: no editor of the application came back, Auto save brought nothing, and nothing has been done since. */
|
|
544
|
+
private fresh;
|
|
545
|
+
/**
|
|
546
|
+
* Starts with a sample of File > Samples instead of the empty ribbon (the input `sample` of the editor: Gridify Designer gives one), and the status bar says where the help is. Only while the editor
|
|
547
|
+
* is fresh: a ribbon that came back, or one that was loaded or changed, stays.
|
|
548
|
+
*/
|
|
549
|
+
startWith(id: string): void;
|
|
550
|
+
/** Auto save could not keep the text of the file (no room, or no storage): its changes are nowhere else, so leaving the page is asked about as without Auto save. */
|
|
551
|
+
private notKept;
|
|
552
|
+
/**
|
|
553
|
+
* Keeps the text of the file, whether it is the one that was saved last (`modified`: it is not), and the file of the project it belongs to. When the browser does not keep it, `tell` says so
|
|
554
|
+
* (once, not for every change).
|
|
555
|
+
*/
|
|
556
|
+
private saveText;
|
|
557
|
+
private forgetText;
|
|
558
|
+
/** What the application would know by a key like `app:paste` and this editor does not: a placeholder is drawn instead, so that the preview stays readable. */
|
|
559
|
+
private previewIcon;
|
|
560
|
+
/** The tabs for `<gfy-ribbon>` of the Editor window. */
|
|
561
|
+
readonly tabs: _angular_core.Signal<GfyRibbonTab[]>;
|
|
562
|
+
/**
|
|
563
|
+
* The tabs for the ribbon of the Preview window: the same, made once more. A control that is used there writes its value into its item (a plain value of the data), and the Editor window, which shows the
|
|
564
|
+
* file, must not show it.
|
|
565
|
+
*/
|
|
566
|
+
readonly liveTabs: _angular_core.Signal<GfyRibbonTab[]>;
|
|
567
|
+
/** The id of the tab of the preview that is shown: the tab of the selected node. */
|
|
568
|
+
readonly activeTabId: _angular_core.Signal<string | undefined>;
|
|
569
|
+
/** The tab of the selected node; the last one that was selected stays while nothing is (a section that is deselected does not take the tab away). */
|
|
570
|
+
private readonly shownTab;
|
|
571
|
+
/** The number of rows of the tabs, the same way the ribbon counts them. */
|
|
572
|
+
readonly rows: _angular_core.Signal<number[]>;
|
|
573
|
+
/** The width the Editor window draws a column at: `colWidth`, or 24 px when it is not set (an application makes the columns as wide as their content then, as the Preview does). */
|
|
574
|
+
readonly drawnColWidth: _angular_core.Signal<number>;
|
|
575
|
+
/** The ribbon with the cell of every item written (see `ops.pinRibbon`): a command that changes a layout starts from it, so no item of the ribbon is left to the grid once the ribbon has been edited. */
|
|
576
|
+
private layoutRoot;
|
|
577
|
+
/** The number of rows of the tab of a node (of the default, for a path that is not in a tab): the operations that keep the places of the items need it. */
|
|
578
|
+
private readonly rowsOf;
|
|
579
|
+
/** The control of the item that the node at `path` is (or that holds the choice it is). `undefined` for a control the editor does not know. */
|
|
580
|
+
private controlOf;
|
|
581
|
+
/**
|
|
582
|
+
* The Editor always draws the columns at a fixed width (`drawnColWidth`), and then the cells stay where they are: an empty column is a cell that is left empty, and the operations do not close it.
|
|
583
|
+
* So a command that moves an item away (or makes it narrower) would leave empty columns at the edge of its section. Those are cut off here, in the sections the command worked on (see `ops.trimColumns`): the first and the last column of a section always hold an item (a section whose `columns` is a text of grid tracks is left as it is).
|
|
584
|
+
*/
|
|
585
|
+
private trimmed;
|
|
586
|
+
/** The inspector of the selected node. */
|
|
587
|
+
readonly inspector: _angular_core.Signal<Inspector$2 | null>;
|
|
588
|
+
/** The properties of the selected node that the rows of the inspector do not hold. */
|
|
589
|
+
readonly otherProperties: _angular_core.Signal<JsonObject>;
|
|
590
|
+
readonly capabilities: _angular_core.Signal<Capabilities$2>;
|
|
591
|
+
/** The problems, for the list: what the reading of the file let pass although JSON does not, and what the check of the ribbon finds. */
|
|
592
|
+
readonly problems: _angular_core.Signal<EditorProblem$2[]>;
|
|
593
|
+
/** The counts of the tabs, the sections and the items, for the status bar. */
|
|
594
|
+
readonly counts: _angular_core.Signal<{
|
|
595
|
+
tabs: number;
|
|
596
|
+
sections: number;
|
|
597
|
+
items: number;
|
|
598
|
+
}>;
|
|
599
|
+
/** The text of the output window. */
|
|
600
|
+
readonly output: _angular_core.Signal<string>;
|
|
601
|
+
say(text: string): void;
|
|
602
|
+
private warn;
|
|
603
|
+
/** Selects a node. */
|
|
604
|
+
select(path: JsonPath | null): void;
|
|
605
|
+
/** Selects the tab that the ribbon of the preview shows (`t0`, `t1`...), as its keys or the mouse change it. */
|
|
606
|
+
selectTabById(id: string): void;
|
|
607
|
+
/** A problem of the list was opened: the node it is about is selected. */
|
|
608
|
+
openProblem(problem: EditorProblem$2): void;
|
|
609
|
+
/**
|
|
610
|
+
* A command changed the ribbon. A result that holds what the ribbon holds already (a cell that an item has, a value that is written again) is no step of undo and no change of the document; only its
|
|
611
|
+
* selection is taken. Says whether the ribbon changed.
|
|
612
|
+
*/
|
|
613
|
+
private run;
|
|
614
|
+
/**
|
|
615
|
+
* The tab that the Editor window shows: the tab of the selection, or the one that was shown last while nothing is selected. The ribbon draws its first tab while none was chosen yet, and when the one
|
|
616
|
+
* that was shown is gone, so that is the first one then (`undefined` for a ribbon without a tab).
|
|
617
|
+
*/
|
|
618
|
+
private shownTabIndex;
|
|
619
|
+
/**
|
|
620
|
+
* Where a new item goes: the section of the selection (the last section of a selected tab, or of the tab that is shown). `section` is `null` when that tab has no section (one is made in it) or there is
|
|
621
|
+
* no tab at all (`tab` is -1 then: a tab with a section is made).
|
|
622
|
+
*/
|
|
623
|
+
private placeForNewItem;
|
|
624
|
+
/** The index of the tab of the selected node. */
|
|
625
|
+
private selectedTab;
|
|
626
|
+
addTab(): void;
|
|
627
|
+
/** A new tab (with a section) after the last one, as the context menu of the empty place of the tab bar adds it. */
|
|
628
|
+
addTabAtEnd(): void;
|
|
629
|
+
addSection(): void;
|
|
630
|
+
/** Adds an item of a control to a section (the one of the selection, if no other is given). */
|
|
631
|
+
addItem(type: string, target?: {
|
|
632
|
+
sectionPath?: JsonPath;
|
|
633
|
+
index?: number;
|
|
634
|
+
cell?: {
|
|
635
|
+
col: number;
|
|
636
|
+
row: number;
|
|
637
|
+
};
|
|
638
|
+
}): void;
|
|
639
|
+
/**
|
|
640
|
+
* Adds a choice: to the end of the choices of the selected item; next to the selected choice (`after` unless said otherwise: that is where a new one is expected), or inside of it (`inside`: a choice
|
|
641
|
+
* that opens a list of choices, as the choices of a menu do).
|
|
642
|
+
*/
|
|
643
|
+
addChoice(where?: 'inside' | 'before' | 'after', entry?: ChoiceEntry): void;
|
|
644
|
+
removeSelected(): void;
|
|
645
|
+
duplicateSelected(): void;
|
|
646
|
+
moveSelected(delta: number): void;
|
|
647
|
+
/** A tab was dragged in the Outline to the place `index` of the tabs (counted without it). */
|
|
648
|
+
moveTabTo(from: number, index: number): void;
|
|
649
|
+
/** A section was dragged in the Outline to the place `index` of the sections of the tab `tabIndex` (counted without it): in its tab, or into another one. */
|
|
650
|
+
moveSectionTo(path: JsonPath, tabIndex: number, index: number): void;
|
|
651
|
+
/** The user changed a row of the inspector. */
|
|
652
|
+
changeRow(id: string, value: unknown): void;
|
|
653
|
+
/** Would Reset change the row `id` of the selected node (take its property out)? Not for a row whose property is not taken out (the control, an id, the kind of a choice) or that has nothing to take. */
|
|
654
|
+
canReset(id: string): boolean;
|
|
655
|
+
/** The user bound a row that is not a text field to a signal of the application (`{"$bind": "name"}`; the row is a code row afterwards). */
|
|
656
|
+
bindRow(id: string): void;
|
|
657
|
+
/** The item that a change of the row `id` of the node at `path` may have made wider (its text, its icon, its control, an input, the text or the icon of a choice), or `null`. */
|
|
658
|
+
private itemWhoseContentChanged;
|
|
659
|
+
/**
|
|
660
|
+
* `defaultRows` of the ribbon: the least number of grid rows of a tab, any whole number from 1. A tab whose items stand lower than that keeps the rows they use, and `rows` of a tab is not less than it
|
|
661
|
+
* either: that is how the library counts them (`tabRows`), so nothing is refused here.
|
|
662
|
+
*/
|
|
663
|
+
setDefaultRows(rows: number): void;
|
|
664
|
+
/** The text of the "other properties" of the selected node; gives the reason when it cannot be used. */
|
|
665
|
+
setOtherProperties(text: string): string | null;
|
|
666
|
+
/** The item at `itemPath` covers all columns of its section (`colSpan: "all"`, see `ops.coverAllColumns`), or goes back to one column. Refused while other items stand in its rows. */
|
|
667
|
+
spanAllColumns(itemPath: JsonPath, on: boolean): void;
|
|
668
|
+
/** Is the room free for an item: no other item stands on the cells (`ignore` is the index of the item that is moved or stretched, which does not count)? */
|
|
669
|
+
isCellFree(sectionPath: JsonPath, cell: {
|
|
670
|
+
col: number;
|
|
671
|
+
row: number;
|
|
672
|
+
colSpan: number;
|
|
673
|
+
rowSpan: number;
|
|
674
|
+
}, ignore: number | null): boolean;
|
|
675
|
+
/** The cells a control covers when it is added: what its item sets by itself. A control that covers all rows (a large button) starts at the first one, wherever it is dropped (`row`). */
|
|
676
|
+
spanOfControl(type: string | null, rows: number): {
|
|
677
|
+
colSpan: number;
|
|
678
|
+
rowSpan: number;
|
|
679
|
+
row?: number;
|
|
680
|
+
};
|
|
681
|
+
/** An item may not be put (or stretched) onto the cells of another one: the move is refused, and the user is told. */
|
|
682
|
+
private cellTaken;
|
|
683
|
+
/** The cells of all the items of a section, as the grid places them (in the order of the items; `null` for an entry that is not an item). */
|
|
684
|
+
placedSection(sectionPath: JsonPath): (PlacedItem | null)[];
|
|
685
|
+
/** What a drop on the boundary before the column `column` of a section would do to the columns (see `ops.plannedColumn`): the hint of the drag asks. */
|
|
686
|
+
plannedColumn(itemPath: JsonPath, sectionPath: JsonPath, column: number): {
|
|
687
|
+
column: number;
|
|
688
|
+
opens: boolean;
|
|
689
|
+
};
|
|
690
|
+
/** The row where the item can stand in a new column before the column `column` of a section, the nearest to `near`; `null` when the items that stretch over the column leave no room. */
|
|
691
|
+
rowInNewColumn(itemPath: JsonPath, sectionPath: JsonPath, column: number, rowSpan: number, near: number): number | null;
|
|
692
|
+
/** An item was dropped on the line of a new column of a section (before the column number `column`, or behind the last one): see `ops.moveItemToNewColumn`. One step of undo. */
|
|
693
|
+
moveItemToNewColumn(itemPath: JsonPath, sectionPath: JsonPath, column: number, row: number): void;
|
|
694
|
+
/** The cell where an item stands in the grid of its section (the one it sets, or the one the grid gives it). */
|
|
695
|
+
placedCell(itemPath: JsonPath): PlacedItem | null;
|
|
696
|
+
/** An item was dropped on a cell: in its own section it only changes its cell, in another one it moves there first. The other items stay where they are (see `ops.moveItemToCell`). One step of undo. */
|
|
697
|
+
moveItemToCell(itemPath: JsonPath, sectionPath: JsonPath, cell: {
|
|
698
|
+
col: number;
|
|
699
|
+
row: number;
|
|
700
|
+
}): void;
|
|
701
|
+
/**
|
|
702
|
+
* An item was stretched in the preview. It grows into the free columns, and where another item stands a column is opened (see `ops.stretchItem`); the cells above and below it must be free, and the rows of the
|
|
703
|
+
* tab must reach. One step of undo.
|
|
704
|
+
*/
|
|
705
|
+
resizeItem(itemPath: JsonPath, size: StretchSize): void;
|
|
706
|
+
/** Can the item be stretched to `size` (see `ops.stretchItem`)? The preview asks while the edge is pulled. */
|
|
707
|
+
canResize(itemPath: JsonPath, size: StretchSize): boolean;
|
|
708
|
+
/**
|
|
709
|
+
* Asks the preview to measure the items and widen those that are too narrow for their content: the columns have a fixed width, and an item that says nothing about its columns has one. `key` joins
|
|
710
|
+
* the widening to the step of undo of the change before it.
|
|
711
|
+
*/
|
|
712
|
+
requestFit(items: readonly JsonPath[], key: string | undefined, announce: false | 'widened'): void;
|
|
713
|
+
/**
|
|
714
|
+
* What the preview measured: for sections (by their path), the columns that the content of their items needs (see `cellsNeeded`), by the index of the item. The items that are narrower are widened
|
|
715
|
+
* (see `ops.fitItems`), in one step of undo. Gives the number of items that became wider.
|
|
716
|
+
*/
|
|
717
|
+
fitItems(needs: readonly {
|
|
718
|
+
readonly section: JsonPath;
|
|
719
|
+
readonly items: ReadonlyMap<number, number>;
|
|
720
|
+
}[], options?: {
|
|
721
|
+
key?: string;
|
|
722
|
+
announce?: false | 'widened';
|
|
723
|
+
}): number;
|
|
724
|
+
/** The arrow keys of the preview: the selected item moves by a cell. */
|
|
725
|
+
nudgeItem(itemPath: JsonPath, dCol: number, dRow: number): void;
|
|
726
|
+
setOption<K extends keyof RibbonOptions>(key: K, value: RibbonOptions[K]): void;
|
|
727
|
+
/**
|
|
728
|
+
* An action of the ribbon in the Preview window: the status bar tells what the application would receive (the action of the item, and the value when there is one). A radio that is chosen
|
|
729
|
+
* turns the other radios of its group off, as the application does (the ribbon sets only the radio that was clicked, see `withRadioGroups`).
|
|
730
|
+
*/
|
|
731
|
+
reportAction(event: GfyRibbonActionEvent): void;
|
|
732
|
+
/** The custom functions were changed (the Ribbon Options window): the text is read as a list such as `s.field:2, s.flag:2` (a predefined function is not a custom one). The same changes of it that follow each other soon are one step of undo. */
|
|
733
|
+
setCustomFunctions(text: string): void;
|
|
734
|
+
undo(): void;
|
|
735
|
+
redo(): void;
|
|
736
|
+
/** Is it all right to replace the document that is being edited? It is asked when the document has changes that were not saved (the tabs, the options or the functions). */
|
|
737
|
+
private mayReplace;
|
|
738
|
+
/** Another document replaces the one that is edited (New, a sample, a file, the clipboard). It is shown from its first tab: the tab that was shown was one of the document before it. */
|
|
739
|
+
private replaceDocument;
|
|
740
|
+
/** A new document: an empty ribbon with the default options and no custom functions, and nothing to undo, as the editor starts. Changes that were not saved are asked about first. */
|
|
741
|
+
newRibbon(): Promise<void>;
|
|
742
|
+
loadSample(id: string): Promise<void>;
|
|
743
|
+
/**
|
|
744
|
+
* A text from outside (a file, the clipboard, a drop) replaces the ribbon. The file of the editor brings its options and its custom functions with it; a bare list of tabs leaves the ones that are set.
|
|
745
|
+
* A text that cannot be read is not loaded: the user is told where it goes wrong, and the ribbon stays. Gives whether the text was loaded (the user may also keep the ribbon that was changed).
|
|
746
|
+
* `name` is what the messages call it, `origin` where it came from (by default a file of that name), for the title in the menu bar.
|
|
747
|
+
*/
|
|
748
|
+
loadFromText(text: string, name: string, origin?: DocumentOrigin): Promise<boolean>;
|
|
749
|
+
/** Asks for a file and loads it. */
|
|
750
|
+
openFile(): void;
|
|
751
|
+
/** File > Open from the project…: a file of the project replaces the ribbon (as a file of the computer does), and the ribbon belongs to it then: Save writes it back there. */
|
|
752
|
+
openFromProject(): Promise<void>;
|
|
753
|
+
/** File > Save: the file goes back into the file of the project that it belongs to (a ribbon that belongs to none asks where, as Save as… does). The ribbon is saved then, as after a download. */
|
|
754
|
+
saveToProject(): Promise<void>;
|
|
755
|
+
/** File > Save as…: the file goes into a file of the project that the user chooses, and belongs to it from then on. */
|
|
756
|
+
saveToProjectAs(): Promise<void>;
|
|
757
|
+
pasteRibbon(): Promise<void>;
|
|
758
|
+
copyOutput(): Promise<void>;
|
|
759
|
+
/**
|
|
760
|
+
* Offers the file of the editor (the functions, the options and the tabs) for download. The document is the one on the disk now: it is not modified until the next change, unless it belongs to a file
|
|
761
|
+
* of the project (then the download is a copy, and the document is saved by Save).
|
|
762
|
+
*/
|
|
763
|
+
downloadFile(): void;
|
|
764
|
+
private downloaded;
|
|
765
|
+
/** Offers what the output window shows as a file. */
|
|
766
|
+
downloadOutput(): void;
|
|
767
|
+
private saveFile;
|
|
768
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<RibbonEditorStore, never>;
|
|
769
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<RibbonEditorStore>;
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
/**
|
|
773
|
+
* An editor of the ribbon of an application. Its file holds the value that goes into `[tabs]` of `<gfy-ribbon>` (a list of `GfyRibbonTab`) with the options of the element and the custom functions of
|
|
774
|
+
* the expressions: it is opened from a file or the clipboard (a bare list of tabs is read as well), edited in the outline, the preview and the inspector, and taken out as the file, as JSON, as
|
|
775
|
+
* TypeScript, with a handler for `(action)` and with the code that loads it. The state is in `RibbonEditorStore`, which this
|
|
776
|
+
* component provides (so every instance has its own), and the windows only read it and call its commands. An application that gives it the files of a project (`files`) gets File > Open from the project…,
|
|
777
|
+
* Save and Save as… besides.
|
|
778
|
+
*/
|
|
779
|
+
declare class RibbonEditor implements OnInit {
|
|
780
|
+
/**
|
|
781
|
+
* The editor is shown by an application that has its own header with the name and the choice of the theme and the density (the application that switches between the editors): the editor
|
|
782
|
+
* then leaves its own name and its own choice out of the menu bar, and it fills the place it is given instead of the whole window. Every editor of the application takes this input.
|
|
783
|
+
*/
|
|
784
|
+
readonly hosted: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
785
|
+
/**
|
|
786
|
+
* The files of a project (a folder of the computer, a server, a place of the application: see `GfyEditorFiles`): File > Open from the project… opens a ribbon of the project, Save writes it back
|
|
787
|
+
* (when the file is still the one that was opened), Save as… writes it under another name. Without them (the default) the editor opens a file of the computer and offers the ribbon for download, as
|
|
788
|
+
* it always did.
|
|
789
|
+
*/
|
|
790
|
+
readonly files: _angular_core.InputSignal<GfyEditorFiles | null>;
|
|
791
|
+
/**
|
|
792
|
+
* The id of a sample of File > Samples that the editor starts with when it has nothing else to show (no ribbon that the application left in it, nothing that Auto save kept). Without it the
|
|
793
|
+
* editor starts with an empty ribbon; Gridify Designer gives `showcase`, the ribbon of a text editor. A ribbon that came back stays.
|
|
794
|
+
*/
|
|
795
|
+
readonly sample: _angular_core.InputSignal<string | null>;
|
|
796
|
+
protected readonly store: RibbonEditorStore;
|
|
797
|
+
protected readonly texts: EditorText;
|
|
798
|
+
/** The Help menu and its window (it closes with the editor). */
|
|
799
|
+
private readonly help;
|
|
800
|
+
private readonly engine;
|
|
801
|
+
protected readonly layout: GfyDockContainerNodeInput;
|
|
802
|
+
protected readonly windowsKey = "gfy-ribbon-editor:windows";
|
|
803
|
+
constructor();
|
|
804
|
+
/** The sample to start with is an input, so it is known only now (the store started before it). */
|
|
805
|
+
ngOnInit(): void;
|
|
806
|
+
/**
|
|
807
|
+
* Every change of the windows is kept at once. The engine saves by itself only when the automatic saving of the page is on (`GfyEngineSettings.autoSaveLayout`, off by default), a setting of the
|
|
808
|
+
* whole page that the editor leaves to the application that shows it.
|
|
809
|
+
*/
|
|
810
|
+
protected saveWindows(): void;
|
|
811
|
+
/**
|
|
812
|
+
* The windows of the View menu: each one checked while it is open (docked or floating), and a click closes an open one or opens a closed one again at its place (the View menu of the engine,
|
|
813
|
+
* `GfyViewTabs`, which follows the tabs as they open and close).
|
|
814
|
+
*/
|
|
815
|
+
private windowItems;
|
|
816
|
+
private resetLayout;
|
|
817
|
+
/** The menus are computed, so the items follow the state. */
|
|
818
|
+
protected readonly menus: _angular_core.Signal<GfyMenu[]>;
|
|
819
|
+
/** The title of the document in the menu bar: its file of the project, or where it came from (a new one, a sample, a file of the computer, the clipboard), with a dot while it has changes. */
|
|
820
|
+
protected readonly title: _angular_core.Signal<DocumentTitle>;
|
|
821
|
+
protected readonly statusItems: _angular_core.Signal<GfyStatusItem[]>;
|
|
822
|
+
protected onFileDragOver(event: DragEvent): void;
|
|
823
|
+
protected onFileDrop(event: DragEvent): void;
|
|
824
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<RibbonEditor, never>;
|
|
825
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<RibbonEditor, "ribbon-editor", never, { "hosted": { "alias": "hosted"; "required": false; "isSignal": true; }; "files": { "alias": "files"; "required": false; "isSignal": true; }; "sample": { "alias": "sample"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
/** `roles`: panels of documents and of tools (the default of the engine). `free`: any tab goes to any panel and the panels have the neutral role `panel` (`dockingMode` of the engine). */
|
|
829
|
+
type DockingMode = 'roles' | 'free';
|
|
830
|
+
/** The options of the engine that change what a layout means. */
|
|
831
|
+
interface LayoutOptions {
|
|
832
|
+
dockingMode: DockingMode;
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
/** What a file says besides the layout. */
|
|
836
|
+
interface FileSettings {
|
|
837
|
+
readonly options: LayoutOptions;
|
|
838
|
+
readonly components: readonly string[];
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
/** What goes with the layout besides the nodes, and is a step of undo as well: the docking mode and the keys of the components the application registers. */
|
|
842
|
+
type Settings = FileSettings;
|
|
843
|
+
/** What a step of undo brings back: the layout (always a container), its options and its components. */
|
|
844
|
+
interface Snapshot extends Settings {
|
|
845
|
+
readonly root: JsonObject;
|
|
846
|
+
}
|
|
847
|
+
interface EditorState$1 {
|
|
848
|
+
/** The layout with its options and components, and the steps before and after it. */
|
|
849
|
+
readonly history: History<Snapshot>;
|
|
850
|
+
/** What the reading of the file that was loaded let pass although JSON does not (comments, single quotes, a declaration around the layout, ...). It is gone with the next change. */
|
|
851
|
+
readonly notes: readonly JsonErrorInfo[];
|
|
852
|
+
/** The container, panel or tab that is selected. */
|
|
853
|
+
readonly selected: JsonPath | null;
|
|
854
|
+
/** The step that was loaded or saved last (a download of the file): the document is modified while the present step is another one. */
|
|
855
|
+
readonly saved: Snapshot;
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
/** What the preview measured of a node, along the split of its parent (the width in a row, the height in a column). */
|
|
859
|
+
interface Measure {
|
|
860
|
+
/** The length in pixels. */
|
|
861
|
+
readonly px: number;
|
|
862
|
+
/** The share of the container in percent. */
|
|
863
|
+
readonly percent: number;
|
|
864
|
+
/**
|
|
865
|
+
* The ratio that gives the node the same length beside its siblings that have a ratio: the ratios share what the lengths leave, so it is the length of the node in the ratio of their sum to
|
|
866
|
+
* their length on the screen. Missing when no open sibling has a ratio (the node would take all that is left whatever its number is).
|
|
867
|
+
*/
|
|
868
|
+
readonly ratio?: number;
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
type NodeKind = 'container' | 'panel' | 'tab';
|
|
872
|
+
/**
|
|
873
|
+
* The four kinds of tab a layout can hold, told by what the engine does with the tab:
|
|
874
|
+
* - `html`: the tab has HTML content (`content`);
|
|
875
|
+
* - `component`: a component of the application, found by its `componentKey` and given its `inputs`;
|
|
876
|
+
* - `element`: a custom element, made from its `componentTag` with `document.createElement`, given its `componentProps` (`kind: 'component'`);
|
|
877
|
+
* - `callback`: the content comes from a callback of the application (`serialize: 'callback'` and `callback`), which gives HTML or a component.
|
|
878
|
+
*/
|
|
879
|
+
type TabKind = 'html' | 'component' | 'element' | 'callback';
|
|
880
|
+
|
|
881
|
+
type TabRole = 'document' | 'tool';
|
|
882
|
+
/** The side of a node where a new panel goes. */
|
|
883
|
+
type PanelSide = 'left' | 'right' | 'top' | 'bottom';
|
|
884
|
+
|
|
885
|
+
/** A row of the inspector. It has the shape of `GfyProperty` of the property grid. */
|
|
886
|
+
interface InspectorRow$1 {
|
|
887
|
+
id: string;
|
|
888
|
+
/** The name of the property the row writes, as it stands in the JSON (`allowDetachOnDrag`), not a translation of it: this is a tool for developers. A row that the editor adds is named like its id. */
|
|
889
|
+
label: string;
|
|
890
|
+
kind: 'text' | 'number' | 'boolean' | 'select';
|
|
891
|
+
category: string;
|
|
892
|
+
description: string;
|
|
893
|
+
options?: readonly {
|
|
894
|
+
value: string;
|
|
895
|
+
label: string;
|
|
896
|
+
}[];
|
|
897
|
+
min?: number;
|
|
898
|
+
max?: number;
|
|
899
|
+
step?: number;
|
|
900
|
+
decimals?: number;
|
|
901
|
+
placeholder?: string;
|
|
902
|
+
defaultValue?: unknown;
|
|
903
|
+
/** The property holds code of the application (`{"$expr": "..."}`): the row is a text row that shows the code with a `=` in front. */
|
|
904
|
+
code?: boolean;
|
|
905
|
+
/** The row cannot be changed (it is grey): the shell where a shell is not possible; the description says why. */
|
|
906
|
+
disabled?: boolean;
|
|
907
|
+
/** The row always has a value (the type of the engine requires the property, or it is the kind of a tab): it has no "not set", and the reset button of the Inspector does not take it out. */
|
|
908
|
+
required?: boolean;
|
|
909
|
+
}
|
|
910
|
+
/** The part of a tab that has an editor of its own under the rows: a text (HTML) or an object (JSON). */
|
|
911
|
+
interface InspectorPart {
|
|
912
|
+
/** The property of the tab it is: `content`, `inputs`, `componentProps` or `callback`. */
|
|
913
|
+
key: string;
|
|
914
|
+
label: string;
|
|
915
|
+
description: string;
|
|
916
|
+
language: 'html' | 'json';
|
|
917
|
+
/** What the editor shows. */
|
|
918
|
+
text: string;
|
|
919
|
+
}
|
|
920
|
+
interface Inspector$1 {
|
|
921
|
+
kind: NodeKind;
|
|
922
|
+
path: JsonPath;
|
|
923
|
+
/** The rows, in the order of the categories. */
|
|
924
|
+
rows: InspectorRow$1[];
|
|
925
|
+
/** The values of the rows, by the id of the row. A property that is not set is missing. */
|
|
926
|
+
values: Record<string, unknown>;
|
|
927
|
+
/** The kind of a tab (`undefined` for the other nodes). */
|
|
928
|
+
tabKind: TabKind | undefined;
|
|
929
|
+
/** The part of a tab (`null` for the other nodes). */
|
|
930
|
+
part: InspectorPart | null;
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
/** Where the nodes of the preview came from: the path of the node with the number `n` is `paths[n]`. */
|
|
934
|
+
interface PreviewLinks {
|
|
935
|
+
readonly paths: readonly JsonPath[];
|
|
936
|
+
}
|
|
937
|
+
/** What `mergeBack` reads of a tab of the engine. */
|
|
938
|
+
interface EngineTabLike {
|
|
939
|
+
readonly id?: string;
|
|
940
|
+
readonly tag?: string;
|
|
941
|
+
}
|
|
942
|
+
/** What `mergeBack` reads of a node of the engine (`GfyDockContainerNode` and `GfyDockPanelNode` have these properties). */
|
|
943
|
+
interface EngineNodeLike {
|
|
944
|
+
readonly id?: string;
|
|
945
|
+
readonly type: string;
|
|
946
|
+
readonly tag?: string;
|
|
947
|
+
readonly role?: string;
|
|
948
|
+
readonly size?: number;
|
|
949
|
+
readonly sizeUnit?: string;
|
|
950
|
+
/** Whether the user can resize the node: the engine moves it with the place of a node (a line it makes around a node takes it over, a node that takes the place of its container gets the container's). */
|
|
951
|
+
readonly resizable?: boolean;
|
|
952
|
+
/** The size while no sibling is collapsed: the size the node has in the layout (see `_baseSize` of the engine). */
|
|
953
|
+
readonly _baseSize?: number;
|
|
954
|
+
readonly collapsed?: boolean;
|
|
955
|
+
readonly activeTab?: number;
|
|
956
|
+
readonly children?: readonly EngineNodeLike[];
|
|
957
|
+
readonly tabs?: readonly EngineTabLike[];
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
/** The kinds of text the output window can show. */
|
|
961
|
+
type OutputKind$1 = 'file' | 'json' | 'typescript' | 'template' | 'loader';
|
|
962
|
+
/** A problem of the list: the problem of the list of the library, and the node it is about (a note on the reading of the file is about none). */
|
|
963
|
+
interface EditorProblem$1 extends GfyProblem {
|
|
964
|
+
readonly nodePath: JsonPath | null;
|
|
965
|
+
}
|
|
966
|
+
/** What the commands that need a selected node can do now. */
|
|
967
|
+
interface Capabilities$1 {
|
|
968
|
+
readonly remove: boolean;
|
|
969
|
+
readonly duplicate: boolean;
|
|
970
|
+
readonly moveUp: boolean;
|
|
971
|
+
readonly moveDown: boolean;
|
|
972
|
+
}
|
|
973
|
+
declare class LayoutEditorStore {
|
|
974
|
+
private readonly toast;
|
|
975
|
+
private readonly box;
|
|
976
|
+
private readonly icons;
|
|
977
|
+
/** The files of the project, while the application gives the editor a place for them (the input `files` of the editor): File > Open from the project…, Save and Save as…. */
|
|
978
|
+
readonly project: EditorProject;
|
|
979
|
+
/** The editor starts with an empty layout (the samples are in File > Samples); with Auto save on, what was kept in the browser replaces it (see `restore`). */
|
|
980
|
+
readonly state: _angular_core.WritableSignal<EditorState$1>;
|
|
981
|
+
readonly root: _angular_core.Signal<JsonObject>;
|
|
982
|
+
readonly notes: _angular_core.Signal<readonly JsonErrorInfo[]>;
|
|
983
|
+
readonly selected: _angular_core.Signal<JsonPath | null>;
|
|
984
|
+
readonly canUndo: _angular_core.Signal<boolean>;
|
|
985
|
+
readonly canRedo: _angular_core.Signal<boolean>;
|
|
986
|
+
/** The document (the layout, its options and its components) has been changed since it was loaded or downloaded. */
|
|
987
|
+
readonly modified: _angular_core.Signal<boolean>;
|
|
988
|
+
/** The docking mode the layout is made for, and the keys of the components the application registers: steps of undo, like the layout. */
|
|
989
|
+
readonly options: _angular_core.Signal<LayoutOptions>;
|
|
990
|
+
readonly components: _angular_core.Signal<readonly string[]>;
|
|
991
|
+
/** The whole file as text: the options, the components and the layout. */
|
|
992
|
+
readonly file: _angular_core.Signal<string>;
|
|
993
|
+
/** The shell is locked in the preview, as it is in the application (the default); off, tabs can be docked into the shell there too. A setting of the editor, not part of the document. */
|
|
994
|
+
readonly lockShell: _angular_core.WritableSignal<boolean>;
|
|
995
|
+
/**
|
|
996
|
+
* Counts the changes of the layout that the preview did not make itself: the preview is built again from the layout when it changes. What the user does in the preview is written into the layout
|
|
997
|
+
* (`mergeFromPreview`) and does not count, so the preview stays as it is while it is used.
|
|
998
|
+
*/
|
|
999
|
+
readonly previewRevision: _angular_core.WritableSignal<number>;
|
|
1000
|
+
/** The number of the times a change of a row was refused: the inspector shows its rows again then (a field would keep the value that was typed). */
|
|
1001
|
+
readonly refusals: _angular_core.WritableSignal<number>;
|
|
1002
|
+
readonly outputKind: _angular_core.WritableSignal<OutputKind$1>;
|
|
1003
|
+
readonly status: _angular_core.WritableSignal<string>;
|
|
1004
|
+
/** File > Auto save: the file is kept in the browser while it is edited and comes back at the next visit. Off by default, and a setting of the editor (not part of the document, not a step of undo). */
|
|
1005
|
+
readonly autoSave: _angular_core.WritableSignal<boolean>;
|
|
1006
|
+
constructor();
|
|
1007
|
+
/** Turns Auto save on or off. Off: what was kept of the document goes at once. On: the document is kept from now on. */
|
|
1008
|
+
setAutoSave(on: boolean): void;
|
|
1009
|
+
private readAutoSave;
|
|
1010
|
+
/**
|
|
1011
|
+
* The file that was kept (Auto save on) replaces the empty layout; one that was not saved after its last change comes back with its changes not saved, and with the file of the project it belongs to.
|
|
1012
|
+
* A text that cannot be read is left alone. Gives whether a file came back.
|
|
1013
|
+
*/
|
|
1014
|
+
private restore;
|
|
1015
|
+
/** The editor has nothing but the empty layout it started with: no editor of the application came back, Auto save brought nothing, and nothing has been done since. */
|
|
1016
|
+
private fresh;
|
|
1017
|
+
/**
|
|
1018
|
+
* Starts with a sample of File > Samples instead of the empty layout (the input `sample` of the editor: Gridify Designer gives one), with the docking mode and the components it is made for, and the
|
|
1019
|
+
* status bar says where the help is. Only while the editor is fresh: a layout that came back, or one that was loaded or changed, stays.
|
|
1020
|
+
*/
|
|
1021
|
+
startWith(id: string): void;
|
|
1022
|
+
/** Auto save could not keep the text of the file (no room, or no storage): its changes are nowhere else, so leaving the page is asked about as without Auto save. */
|
|
1023
|
+
private notKept;
|
|
1024
|
+
/**
|
|
1025
|
+
* Keeps the text of the file, whether it is the one that was saved last (`modified`: it is not), and the file of the project it belongs to. When the browser does not keep it, `tell` says so
|
|
1026
|
+
* (once, not for every change).
|
|
1027
|
+
*/
|
|
1028
|
+
private saveText;
|
|
1029
|
+
private forgetText;
|
|
1030
|
+
/** The inspector of the selected node. */
|
|
1031
|
+
readonly inspector: _angular_core.Signal<Inspector$1 | null>;
|
|
1032
|
+
/** The properties of the selected node that the rows of the inspector do not hold. */
|
|
1033
|
+
readonly otherProperties: _angular_core.Signal<JsonObject>;
|
|
1034
|
+
/** A command is offered where it does something: the same commands are tried on the layout, and one that would be refused (or would change nothing) is grey. */
|
|
1035
|
+
readonly capabilities: _angular_core.Signal<Capabilities$1>;
|
|
1036
|
+
/** The problems, for the list: what the reading of the file let pass although JSON does not, and what the check of the layout finds. */
|
|
1037
|
+
readonly problems: _angular_core.Signal<EditorProblem$1[]>;
|
|
1038
|
+
/** The counts of the panels and the tabs, for the status bar. */
|
|
1039
|
+
readonly counts: _angular_core.Signal<{
|
|
1040
|
+
panels: number;
|
|
1041
|
+
tabs: number;
|
|
1042
|
+
}>;
|
|
1043
|
+
/** The keys of the components that the application registers: those of the Options, then the others that the tabs use. */
|
|
1044
|
+
readonly registered: _angular_core.Signal<string[]>;
|
|
1045
|
+
/** The text of the output window. */
|
|
1046
|
+
readonly output: _angular_core.Signal<string>;
|
|
1047
|
+
say(text: string): void;
|
|
1048
|
+
private warn;
|
|
1049
|
+
/** Selects a node. */
|
|
1050
|
+
select(path: JsonPath | null): void;
|
|
1051
|
+
/** A problem of the list was opened: the node it is about is selected. */
|
|
1052
|
+
openProblem(problem: EditorProblem$1): void;
|
|
1053
|
+
/** A change that does not come from the preview: the layout is the new one, and the preview is built from it. */
|
|
1054
|
+
private replaceState;
|
|
1055
|
+
/** Takes the result of a command as a step of the document. Gives whether the layout changed (a command that could do nothing says nothing). */
|
|
1056
|
+
private run;
|
|
1057
|
+
/**
|
|
1058
|
+
* What the user did in the preview (a splitter dragged, a tab moved, a panel collapsed, another tab shown) is written into the layout. `base` and `links` are what the preview was made from (see
|
|
1059
|
+
* `mergeBack`); the result is the whole state of the preview, not a step on the layout as it is now. The preview is not built again. Gives whether the layout changed.
|
|
1060
|
+
*/
|
|
1061
|
+
mergeFromPreview(base: JsonValue, links: PreviewLinks, engine: EngineNodeLike | null, mergeKey: string): boolean;
|
|
1062
|
+
/** The measure the preview takes of a node (its size on the screen), for the change of the unit of its size; set by the window of the preview. */
|
|
1063
|
+
private measurer;
|
|
1064
|
+
setMeasurer(measurer: ((path: JsonPath) => Measure | undefined) | null): void;
|
|
1065
|
+
/** A new empty tab, HTML or a component, for documents or for tools: in the selected panel, or the first one that takes the role, or in a new panel. */
|
|
1066
|
+
addTab(kind: TabKind, role: TabRole): void;
|
|
1067
|
+
/** A new panel with a new tab (a component), for documents or for tools, on a side of the selected node. A side where the panel would stand outside the shell is refused. */
|
|
1068
|
+
addPanel(role: TabRole, side: PanelSide): void;
|
|
1069
|
+
/** Can a panel go on that side of the selected node (the menus grey the sides that cannot)? */
|
|
1070
|
+
canAddPanel(role: TabRole, side: PanelSide): boolean;
|
|
1071
|
+
removeSelected(): void;
|
|
1072
|
+
duplicateSelected(): void;
|
|
1073
|
+
moveSelected(delta: number): void;
|
|
1074
|
+
/**
|
|
1075
|
+
* The user changed a row of the inspector. The shell may be refused (it has rules), a fixed role and a collapse that the engine would undo are refused too; the unit of a size keeps the room the
|
|
1076
|
+
* node has now, as the preview measured it. A change after which the engine would tidy the layout (a container merged into the one around it) is tidied at once, and the user is told.
|
|
1077
|
+
*/
|
|
1078
|
+
changeRow(id: string, value: unknown): void;
|
|
1079
|
+
/** The text of the "other properties" of the selected node; gives the reason when it cannot be used. */
|
|
1080
|
+
setOtherProperties(text: string): string | null;
|
|
1081
|
+
/** The text of the part of the selected tab (its HTML, inputs, properties or callback); gives the reason when it cannot be used. */
|
|
1082
|
+
setPart(text: string): string | null;
|
|
1083
|
+
/**
|
|
1084
|
+
* The docking mode the layout is made for (the Options window). The roles of the panels go with it, in the same step of undo (`convertRoles`): the neutral role `panel` in the free mode, the
|
|
1085
|
+
* role of their tabs in the mode with roles (a panel that holds both is left as it is, and the Problems window says where). The free mode keeps no empty panel either: the engine takes them
|
|
1086
|
+
* out when it shows the layout, and so does the editor.
|
|
1087
|
+
*/
|
|
1088
|
+
setDockingMode(mode: DockingMode): void;
|
|
1089
|
+
/** The keys of the components the application registers (the Options window), from the text typed: separated by commas, spaces or lines. */
|
|
1090
|
+
setComponents(text: string): void;
|
|
1091
|
+
undo(): void;
|
|
1092
|
+
redo(): void;
|
|
1093
|
+
/** Is it all right to replace the document that is being edited? A document that was changed since it was loaded or saved is asked about. */
|
|
1094
|
+
private mayReplace;
|
|
1095
|
+
/** A new document: an empty layout with the default docking mode and no components, and nothing to undo. A document that was changed is asked about first. */
|
|
1096
|
+
newLayout(): Promise<void>;
|
|
1097
|
+
loadSample(id: string): Promise<void>;
|
|
1098
|
+
/**
|
|
1099
|
+
* A text from outside (a file, the clipboard, a drop) replaces the layout. The file of the editor brings its options and its components with it; a bare layout leaves the ones that are set. A text
|
|
1100
|
+
* that cannot be read is not loaded: the user is told where it goes wrong, and the layout stays. Gives whether the text was loaded (the user may also keep the layout that was changed). `name` is
|
|
1101
|
+
* what the messages call it, `origin` where it came from (by default a file of that name), for the title in the menu bar.
|
|
1102
|
+
*/
|
|
1103
|
+
loadFromText(text: string, name: string, origin?: DocumentOrigin): Promise<boolean>;
|
|
1104
|
+
/** File > Open from the project…: a file of the project replaces the layout (as a file of the computer does), and the layout belongs to it then: Save writes it back there. */
|
|
1105
|
+
openFromProject(): Promise<void>;
|
|
1106
|
+
/** File > Save: the file goes back into the file of the project that it belongs to (a layout that belongs to none asks where, as Save as… does). The layout is saved then, as after a download. */
|
|
1107
|
+
saveToProject(): Promise<void>;
|
|
1108
|
+
/** File > Save as…: the file goes into a file of the project that the user chooses, and belongs to it from then on. */
|
|
1109
|
+
saveToProjectAs(): Promise<void>;
|
|
1110
|
+
/** Asks for a file and loads it. */
|
|
1111
|
+
openFile(): void;
|
|
1112
|
+
pasteLayout(): Promise<void>;
|
|
1113
|
+
copyOutput(): Promise<void>;
|
|
1114
|
+
/**
|
|
1115
|
+
* Offers the file of the editor (the options, the components and the layout) for download. The document is saved then (it is not modified until the next change), unless it belongs to a file of the
|
|
1116
|
+
* project: then the download is a copy, and the document is saved by Save.
|
|
1117
|
+
*/
|
|
1118
|
+
downloadFile(): void;
|
|
1119
|
+
private downloaded;
|
|
1120
|
+
/** Offers what the output window shows as a file. */
|
|
1121
|
+
downloadOutput(): void;
|
|
1122
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<LayoutEditorStore, never>;
|
|
1123
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<LayoutEditorStore>;
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
/**
|
|
1127
|
+
* An editor of the layout of the docking engine. Its file holds the value that goes into `[defaultLayout]` of `<gfy-docking-engine>` (a container with panels and tabs) with the docking mode and the
|
|
1128
|
+
* components it is made for: it is opened from a file or the clipboard (a bare layout is read as well) or started empty, edited in the outline, the preview and the inspector, and taken out as the file, as
|
|
1129
|
+
* JSON, as TypeScript, as the template and as the code that loads it. The state is in `LayoutEditorStore`, which this component provides (so every instance has its own), and the windows only read it
|
|
1130
|
+
* and call its commands. An application that gives it the files of a project (`files`) gets File > Open from the project…, Save and Save as… besides. The editor is English only.
|
|
1131
|
+
*/
|
|
1132
|
+
declare class LayoutEditor implements OnInit {
|
|
1133
|
+
/**
|
|
1134
|
+
* The editor is shown by an application that has its own header with the name and the choice of the theme and the density (the application that switches between the editors): the editor then leaves
|
|
1135
|
+
* its own name and its own choice out of the menu bar, and it fills the place it is given instead of the whole window. Every editor of the application takes this input.
|
|
1136
|
+
*/
|
|
1137
|
+
readonly hosted: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
1138
|
+
/**
|
|
1139
|
+
* The files of a project (a folder of the computer, a server, a place of the application: see `GfyEditorFiles`): File > Open from the project… opens a layout of the project, Save writes it back
|
|
1140
|
+
* (when the file is still the one that was opened), Save as… writes it under another name. Without them (the default) the editor opens a file of the computer and offers the layout for download, as
|
|
1141
|
+
* it always did.
|
|
1142
|
+
*/
|
|
1143
|
+
readonly files: _angular_core.InputSignal<GfyEditorFiles | null>;
|
|
1144
|
+
/**
|
|
1145
|
+
* The id of a sample of File > Samples that the editor starts with when it has nothing else to show (no layout that the application left in it, nothing that Auto save kept). Without it the
|
|
1146
|
+
* editor starts with an empty layout; Gridify Designer gives `ide`, the workbench. A layout that came back stays.
|
|
1147
|
+
*/
|
|
1148
|
+
readonly sample: _angular_core.InputSignal<string | null>;
|
|
1149
|
+
protected readonly store: LayoutEditorStore;
|
|
1150
|
+
/** The Help menu and its window (it closes with the editor). */
|
|
1151
|
+
private readonly help;
|
|
1152
|
+
private readonly engine;
|
|
1153
|
+
protected readonly layout: GfyDockContainerNodeInput;
|
|
1154
|
+
/** The places of the windows are kept in the browser by the engine of the editor (the engine of the Preview keeps nothing), and come back at the next visit. */
|
|
1155
|
+
protected readonly windowsKey = "gfy-layout-editor:windows";
|
|
1156
|
+
constructor();
|
|
1157
|
+
/** The sample to start with is an input, so it is known only now (the store started before it). */
|
|
1158
|
+
ngOnInit(): void;
|
|
1159
|
+
/**
|
|
1160
|
+
* Every change of the windows is kept at once. The engine saves by itself only when the automatic saving of the page is on (`GfyEngineSettings.autoSaveLayout`), a setting of the whole page
|
|
1161
|
+
* that the editor leaves to the application that shows it.
|
|
1162
|
+
*/
|
|
1163
|
+
protected saveWindows(): void;
|
|
1164
|
+
/**
|
|
1165
|
+
* The windows of the View menu: each one checked while it is open (docked or floating), and a click closes an open one or opens a closed one again at its place (the View menu of the engine,
|
|
1166
|
+
* `GfyViewTabs`, which follows the tabs as they open and close).
|
|
1167
|
+
*/
|
|
1168
|
+
private windowItems;
|
|
1169
|
+
/** The windows go back to where they are at the start (the engine forgets the places it kept). */
|
|
1170
|
+
private resetWindows;
|
|
1171
|
+
/** The menus are computed, so the items follow the state. */
|
|
1172
|
+
protected readonly menus: _angular_core.Signal<GfyMenu[]>;
|
|
1173
|
+
/** The title of the document in the menu bar: its file of the project, or where it came from (a new one, a sample, a file of the computer, the clipboard), with a dot while it has changes. */
|
|
1174
|
+
protected readonly title: _angular_core.Signal<DocumentTitle>;
|
|
1175
|
+
protected readonly statusItems: _angular_core.Signal<GfyStatusItem[]>;
|
|
1176
|
+
protected onFileDragOver(event: DragEvent): void;
|
|
1177
|
+
protected onFileDrop(event: DragEvent): void;
|
|
1178
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<LayoutEditor, never>;
|
|
1179
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<LayoutEditor, "layout-editor", never, { "hosted": { "alias": "hosted"; "required": false; "isSignal": true; }; "files": { "alias": "files"; "required": false; "isSignal": true; }; "sample": { "alias": "sample"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
1180
|
+
}
|
|
1181
|
+
|
|
1182
|
+
type FormFile = GfyFormLayoutFile;
|
|
1183
|
+
type FormElement = GfyFormElement;
|
|
1184
|
+
type FormPlace = GfyFormPlace;
|
|
1185
|
+
/** A rectangle of cells: the first column and row (from 1) and how many it covers. */
|
|
1186
|
+
interface Cells {
|
|
1187
|
+
readonly col: number;
|
|
1188
|
+
readonly row: number;
|
|
1189
|
+
readonly colSpan: number;
|
|
1190
|
+
readonly rowSpan: number;
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
/** What the Inspector shows while no element is selected: the variant that is edited, its form, or the file. */
|
|
1194
|
+
type Scope = 'variant' | 'form' | 'file';
|
|
1195
|
+
interface Selection {
|
|
1196
|
+
/** The form that is edited. */
|
|
1197
|
+
readonly form: string;
|
|
1198
|
+
/** The variant of it that is edited, by its `minWidth`. */
|
|
1199
|
+
readonly minWidth: number;
|
|
1200
|
+
/** The selected elements of the form, the one the Inspector shows first. */
|
|
1201
|
+
readonly names: readonly string[];
|
|
1202
|
+
readonly scope: Scope;
|
|
1203
|
+
}
|
|
1204
|
+
interface EditorState {
|
|
1205
|
+
readonly history: History<FormFile>;
|
|
1206
|
+
readonly selection: Selection;
|
|
1207
|
+
/** What the reading of the file that was loaded let pass or mended; it is gone with the next change. */
|
|
1208
|
+
readonly notes: readonly JsonErrorInfo[];
|
|
1209
|
+
/** The file as it was loaded or saved last: the document is modified while the present one is another. */
|
|
1210
|
+
readonly saved: FormFile;
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
/** A layer an element is shown in: the group of layers and the layer (a page of a property sheet is a layer of the group named by its sheet). */
|
|
1214
|
+
interface LayerRef {
|
|
1215
|
+
readonly group: string;
|
|
1216
|
+
readonly layer: string;
|
|
1217
|
+
/** The layer is the one that is shown while nothing else is chosen: the first one of its group (the first page that has a place, for a sheet). */
|
|
1218
|
+
readonly first: boolean;
|
|
1219
|
+
}
|
|
1220
|
+
/** An element of a form in one variant. */
|
|
1221
|
+
interface Placed {
|
|
1222
|
+
readonly name: string;
|
|
1223
|
+
readonly element: FormElement;
|
|
1224
|
+
/** The group it is in, `null` at the top of the form. */
|
|
1225
|
+
readonly parent: string | null;
|
|
1226
|
+
readonly depth: number;
|
|
1227
|
+
/** Its number in the order of the page, from 0. */
|
|
1228
|
+
readonly order: number;
|
|
1229
|
+
/** Its place in the variant: counted in the cells of its group, or of the grid. */
|
|
1230
|
+
readonly place: FormPlace | null;
|
|
1231
|
+
/** Its cells in the grid of the variant; `null` when it has no place, or a group around it has none. */
|
|
1232
|
+
readonly cells: Cells | null;
|
|
1233
|
+
/** The cells its place is counted in (and has to lie in): the cells of its group, or the whole grid; `null` when the group has no place. */
|
|
1234
|
+
readonly bounds: Cells | null;
|
|
1235
|
+
/** Its own layer and those of the groups around it, and the page it is in. */
|
|
1236
|
+
readonly layers: readonly LayerRef[];
|
|
1237
|
+
}
|
|
1238
|
+
/** The edge cells of a container that its frame (or the tabs of a sheet) takes: how many rows and columns on each side its elements leave free. */
|
|
1239
|
+
interface Insets {
|
|
1240
|
+
readonly top: number;
|
|
1241
|
+
readonly right: number;
|
|
1242
|
+
readonly bottom: number;
|
|
1243
|
+
readonly left: number;
|
|
1244
|
+
}
|
|
1245
|
+
|
|
1246
|
+
/** The form and the variant that the editor works on. */
|
|
1247
|
+
interface Ctx {
|
|
1248
|
+
readonly form: string;
|
|
1249
|
+
readonly minWidth: number;
|
|
1250
|
+
}
|
|
1251
|
+
/** Where an element goes: a list (`parent`) and the cells of the grid of the variant that is edited. */
|
|
1252
|
+
interface Move {
|
|
1253
|
+
readonly name: string;
|
|
1254
|
+
readonly parent: string | null;
|
|
1255
|
+
readonly cells: Cells;
|
|
1256
|
+
}
|
|
1257
|
+
/** How elements are lined up with the first selected one: an edge or the middle across or down, or its width, its height or both. */
|
|
1258
|
+
type AlignHow = 'left' | 'center' | 'right' | 'top' | 'middle' | 'bottom' | 'width' | 'height' | 'size';
|
|
1259
|
+
/** The empty tracks at the edges of a variant. */
|
|
1260
|
+
interface EmptyEdges {
|
|
1261
|
+
readonly top: number;
|
|
1262
|
+
readonly bottom: number;
|
|
1263
|
+
readonly left: number;
|
|
1264
|
+
readonly right: number;
|
|
1265
|
+
}
|
|
1266
|
+
|
|
1267
|
+
type ToolId = 'text-field' | 'text-area' | 'password' | 'date' | 'select' | 'combobox' | 'checkbox' | 'radio-group' | 'switch' | 'spinner' | 'button' | 'styled-button' | 'split-button' | 'dropdown-button' | 'time' | 'date-time' | 'mask' | 'multi-select' | 'tags' | 'slider' | 'toggle-group' | 'color' | 'file-upload' | 'picture' | 'gallery' | 'display' | 'own' | 'separator' | 'label-above' | 'label-beside' | 'label' | 'caption' | 'text' | 'group-box' | 'group' | 'property-sheet' | 'repeated-group' | 'subform';
|
|
1268
|
+
|
|
1269
|
+
/** A row of the Inspector, in the shape of `GfyProperty` of the property grid. */
|
|
1270
|
+
interface InspectorRow {
|
|
1271
|
+
readonly id: string;
|
|
1272
|
+
/** The name of the property as the file has it: this is a tool for developers. */
|
|
1273
|
+
readonly label: string;
|
|
1274
|
+
readonly kind: 'text' | 'number' | 'boolean' | 'select' | 'readonly';
|
|
1275
|
+
readonly category: string;
|
|
1276
|
+
readonly description: string;
|
|
1277
|
+
readonly options?: readonly {
|
|
1278
|
+
value: unknown;
|
|
1279
|
+
label: string;
|
|
1280
|
+
}[];
|
|
1281
|
+
readonly min?: number;
|
|
1282
|
+
readonly max?: number;
|
|
1283
|
+
readonly step?: number;
|
|
1284
|
+
readonly unit?: string;
|
|
1285
|
+
readonly placeholder?: string;
|
|
1286
|
+
readonly defaultValue?: unknown;
|
|
1287
|
+
readonly disabled?: boolean;
|
|
1288
|
+
}
|
|
1289
|
+
interface Inspector {
|
|
1290
|
+
readonly kind: 'element' | 'elements' | 'variant' | 'form' | 'file';
|
|
1291
|
+
/** What is inspected, for the head of the window: the kind and the name. */
|
|
1292
|
+
readonly title: string;
|
|
1293
|
+
readonly subtitle: string;
|
|
1294
|
+
readonly rows: InspectorRow[];
|
|
1295
|
+
readonly values: Record<string, unknown>;
|
|
1296
|
+
}
|
|
1297
|
+
/** The columns or the rows of the variant that are selected (a click on a number in the Editor; Shift and a click or a drag over the numbers: a range; Ctrl and a click: one more or one less). */
|
|
1298
|
+
interface TrackRef {
|
|
1299
|
+
readonly axis: 'col' | 'row';
|
|
1300
|
+
/** The numbers of the tracks, from 1, in the order of the grid; one at least. */
|
|
1301
|
+
readonly indices: readonly number[];
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
/** What a problem is about: the form, the variant and the element (each when the problem names it). */
|
|
1305
|
+
interface ProblemTarget {
|
|
1306
|
+
readonly form?: string;
|
|
1307
|
+
readonly minWidth?: number;
|
|
1308
|
+
readonly element?: string;
|
|
1309
|
+
}
|
|
1310
|
+
/** A problem of the list (the shape of `GfyProblem` of the problem list of the library), with what it leads to. */
|
|
1311
|
+
interface EditorProblem {
|
|
1312
|
+
readonly id: string;
|
|
1313
|
+
readonly severity: 'error' | 'warning' | 'info';
|
|
1314
|
+
readonly code: string;
|
|
1315
|
+
readonly message: string;
|
|
1316
|
+
/** Where, as the column of the list shows it: the form, the variant and the element. */
|
|
1317
|
+
readonly file: string;
|
|
1318
|
+
/** The path in the file (the tooltip). */
|
|
1319
|
+
readonly path: string;
|
|
1320
|
+
readonly line?: number;
|
|
1321
|
+
readonly column?: number;
|
|
1322
|
+
readonly target: ProblemTarget | null;
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
/** The kinds of text the Output window can show. */
|
|
1326
|
+
type OutputKind = 'file' | 'template' | 'component';
|
|
1327
|
+
/** Where an element that the variant does not place is dropped from its node in the Outline: the Editor (the pointer in the coordinates of the window). */
|
|
1328
|
+
interface PlaceTarget {
|
|
1329
|
+
/** The pointer is here: the frame shows where the element would go (green on free cells; none off the paper). */
|
|
1330
|
+
over(name: string, clientX: number, clientY: number): void;
|
|
1331
|
+
/** Dropped here: placed on free cells (on taken ones the Editor says why not; off the paper nothing happens). */
|
|
1332
|
+
drop(name: string, clientX: number, clientY: number): void;
|
|
1333
|
+
/** The drag ended elsewhere, or was given up: the frame goes. */
|
|
1334
|
+
leave(): void;
|
|
1335
|
+
}
|
|
1336
|
+
/** The settings of the Editor and the Preview that are not part of the file (no step of undo): kept for the next store, not in the file. */
|
|
1337
|
+
interface ViewState {
|
|
1338
|
+
/** The active layer of each group of layers, by the form. */
|
|
1339
|
+
readonly layers: Readonly<Record<string, Readonly<Record<string, string>>>>;
|
|
1340
|
+
/** The page shown in each property sheet, by the form. */
|
|
1341
|
+
readonly pages: Readonly<Record<string, Readonly<Record<string, string>>>>;
|
|
1342
|
+
/** The layer that new elements get, by the form (none when missing). */
|
|
1343
|
+
readonly newLayer: Readonly<Record<string, string>>;
|
|
1344
|
+
/** The width the Editor draws the variant at, in px; `null` fits it to the window (within the widths of the variant). */
|
|
1345
|
+
readonly designWidth: number | null;
|
|
1346
|
+
/** The lines of the cells are drawn. */
|
|
1347
|
+
readonly showGrid: boolean;
|
|
1348
|
+
/** The width of the form in the Preview, in px; `null` fits the window. */
|
|
1349
|
+
readonly previewWidth: number | null;
|
|
1350
|
+
/** The Preview takes the width the Editor draws the form at (its own slider, Fit and right edge are off then). */
|
|
1351
|
+
readonly previewFollows?: boolean;
|
|
1352
|
+
}
|
|
1353
|
+
/** What the commands that need a selection can do now (the menus grey the others). */
|
|
1354
|
+
interface Capabilities {
|
|
1355
|
+
readonly remove: boolean;
|
|
1356
|
+
readonly duplicate: boolean;
|
|
1357
|
+
readonly copy: boolean;
|
|
1358
|
+
readonly paste: boolean;
|
|
1359
|
+
readonly wrap: boolean;
|
|
1360
|
+
readonly unwrap: boolean;
|
|
1361
|
+
readonly unplace: boolean;
|
|
1362
|
+
readonly addLabel: boolean;
|
|
1363
|
+
/** Two elements or more are selected and the first of them has a place in the variant: the others can be lined up with it. */
|
|
1364
|
+
readonly align: boolean;
|
|
1365
|
+
}
|
|
1366
|
+
declare class FormEditorStore {
|
|
1367
|
+
private readonly toast;
|
|
1368
|
+
private readonly box;
|
|
1369
|
+
private readonly dialogs;
|
|
1370
|
+
private readonly icons;
|
|
1371
|
+
/** The files of the project, while the application gives the editor a place for them (the input `files` of the editor): File > Open from the project…, Save and Save as…. */
|
|
1372
|
+
readonly project: EditorProject;
|
|
1373
|
+
readonly state: _angular_core.WritableSignal<EditorState>;
|
|
1374
|
+
readonly file: _angular_core.Signal<_gridify_studio.GfyFormLayoutFile>;
|
|
1375
|
+
readonly selection: _angular_core.Signal<Selection>;
|
|
1376
|
+
readonly selected: _angular_core.Signal<readonly string[]>;
|
|
1377
|
+
readonly notes: _angular_core.Signal<readonly JsonErrorInfo[]>;
|
|
1378
|
+
readonly canUndo: _angular_core.Signal<boolean>;
|
|
1379
|
+
readonly canRedo: _angular_core.Signal<boolean>;
|
|
1380
|
+
readonly modified: _angular_core.Signal<boolean>;
|
|
1381
|
+
/** The text of the file. */
|
|
1382
|
+
readonly fileText: _angular_core.Signal<string>;
|
|
1383
|
+
/** The form that is edited and its variant. */
|
|
1384
|
+
readonly form: _angular_core.Signal<_gridify_studio.GfyFormDefinition | undefined>;
|
|
1385
|
+
readonly variant: _angular_core.Signal<_gridify_studio.GfyFormVariant | undefined>;
|
|
1386
|
+
readonly variants: _angular_core.Signal<_gridify_studio.GfyFormVariant[]>;
|
|
1387
|
+
/** The division of the file (as the library reads it: a whole number from 1 to 4, else the default). */
|
|
1388
|
+
readonly division: _angular_core.Signal<number>;
|
|
1389
|
+
readonly ctx: _angular_core.Signal<Ctx>;
|
|
1390
|
+
readonly view: _angular_core.WritableSignal<ViewState>;
|
|
1391
|
+
readonly outputKind: _angular_core.WritableSignal<OutputKind>;
|
|
1392
|
+
readonly status: _angular_core.WritableSignal<string>;
|
|
1393
|
+
/** Counts the times a window asked the Editor to take the focus (the Toolbox after a click adds a tool). */
|
|
1394
|
+
readonly focusEditor: _angular_core.WritableSignal<number>;
|
|
1395
|
+
readonly autoSave: _angular_core.WritableSignal<boolean>;
|
|
1396
|
+
/** The tool that is dragged from the Toolbox (the Editor sizes its mark by it). */
|
|
1397
|
+
readonly dragTool: _angular_core.WritableSignal<ToolId | null>;
|
|
1398
|
+
/** The Editor, while it is shown: an element that the variant does not place, dragged from its node in the Outline, is dropped there. */
|
|
1399
|
+
placeTarget: PlaceTarget | null;
|
|
1400
|
+
/** The variant whose Inspector is shown (`form|minWidth`; empty while the Inspector shows the form or the file): the columns or the rows that are selected belong to it. */
|
|
1401
|
+
private readonly trackScope;
|
|
1402
|
+
/** The columns or the rows whose numbers were selected, with the variant they belong to. */
|
|
1403
|
+
private readonly chosenTrack;
|
|
1404
|
+
/**
|
|
1405
|
+
* The columns or the rows whose numbers are selected in the Editor (a click, Shift or Ctrl and a click, a drag over the numbers): the Inspector of the variant shows their size. They belong to
|
|
1406
|
+
* the variant that was edited then: another form or variant, or the Inspector of the form or the file, has none. An edit keeps them.
|
|
1407
|
+
*/
|
|
1408
|
+
readonly track: _angular_core.Signal<TrackRef | null>;
|
|
1409
|
+
/** The widths of the columns as the Editor draws the variant now, in px (the Editor tells them): what Keep their width writes. */
|
|
1410
|
+
readonly drawnColumns: _angular_core.WritableSignal<readonly number[]>;
|
|
1411
|
+
/** The width the Editor draws the form at, in px (the Editor tells it while it has a size; `null` before it was drawn): what the Preview takes when it follows the Editor. */
|
|
1412
|
+
readonly editorWidth: _angular_core.WritableSignal<number | null>;
|
|
1413
|
+
/** The mode in which a click on the elements gives them the order of the page, one after another (Set tab order). */
|
|
1414
|
+
readonly tabOrderMode: _angular_core.WritableSignal<boolean>;
|
|
1415
|
+
/** In the mode of the order of the page: where the next click puts an element in each list. */
|
|
1416
|
+
private tabCounters;
|
|
1417
|
+
/** The elements that were clicked since the mode of the order of the page was turned on: the Editor marks them (their numbers in the color of the selection). */
|
|
1418
|
+
readonly tabOrdered: _angular_core.WritableSignal<ReadonlySet<string>>;
|
|
1419
|
+
/** Counts the refusals of a change of a row: the Inspector shows its rows again then (a field would keep what was typed). */
|
|
1420
|
+
readonly refusals: _angular_core.WritableSignal<number>;
|
|
1421
|
+
/** The element whose text is edited in the Editor itself (a double click). */
|
|
1422
|
+
readonly editingText: _angular_core.WritableSignal<string | null>;
|
|
1423
|
+
/** The text that is edited in place is the caption of a control (a check box, a switch, a button: `preview.props.label`), not the name of the input. */
|
|
1424
|
+
readonly editingCaption: _angular_core.WritableSignal<boolean>;
|
|
1425
|
+
private readonly clipboard;
|
|
1426
|
+
/** Every element of the form in the variant. */
|
|
1427
|
+
readonly placed: _angular_core.Signal<Placed[]>;
|
|
1428
|
+
readonly placedByName: _angular_core.Signal<Map<string, Placed>>;
|
|
1429
|
+
/** The active layer of every group of the form, and the page of every property sheet (a page is a layer of the group named by its sheet). */
|
|
1430
|
+
readonly active: _angular_core.Signal<Record<string, string>>;
|
|
1431
|
+
/** The elements that the Editor draws: they have cells and their layers and pages are the active ones. */
|
|
1432
|
+
readonly visible: _angular_core.Signal<Set<string>>;
|
|
1433
|
+
/** The elements that have no place in the variant though their list has one: the strip under the grid offers them. */
|
|
1434
|
+
readonly unplaced: _angular_core.Signal<Placed[]>;
|
|
1435
|
+
/** The layer new elements get (in the form that is edited). */
|
|
1436
|
+
readonly newLayer: _angular_core.Signal<string>;
|
|
1437
|
+
/** The width the Editor draws the variant at when it is not fitted to the window (`null`: fit). */
|
|
1438
|
+
readonly designWidth: _angular_core.Signal<number | null>;
|
|
1439
|
+
/** The narrowest a form of the file gets (`minFormWidth`), in px; 0 for no limit. */
|
|
1440
|
+
readonly minFormWidth: _angular_core.Signal<number>;
|
|
1441
|
+
/** The widths the variant is used for: from its `minWidth` up to the next variant (or without an end). */
|
|
1442
|
+
readonly variantRange: _angular_core.Signal<{
|
|
1443
|
+
from: number;
|
|
1444
|
+
to: number | null;
|
|
1445
|
+
}>;
|
|
1446
|
+
/** The file as the library loads it (the texts with code show their first text), for the Problems and the Preview. */
|
|
1447
|
+
readonly loaded: _angular_core.Signal<_gridify_studio.GfyFormLoadResult>;
|
|
1448
|
+
readonly layout: _angular_core.Signal<GfyFormLayout | null>;
|
|
1449
|
+
/** The problems: what the reading of the file mended, what the library reports and what the editor checks. */
|
|
1450
|
+
readonly problems: _angular_core.Signal<EditorProblem[]>;
|
|
1451
|
+
/** The problems of each element of the form that is edited, the worst first (the Outline and the Editor mark them). */
|
|
1452
|
+
readonly problemsByElement: _angular_core.Signal<Map<string, "error" | "warning">>;
|
|
1453
|
+
readonly inspector: _angular_core.Signal<Inspector | null>;
|
|
1454
|
+
readonly output: _angular_core.Signal<string>;
|
|
1455
|
+
readonly capabilities: _angular_core.Signal<Capabilities>;
|
|
1456
|
+
/** The forms a subform of the form that is edited can place. */
|
|
1457
|
+
readonly subformTargets: _angular_core.Signal<string[]>;
|
|
1458
|
+
constructor();
|
|
1459
|
+
setAutoSave(on: boolean): void;
|
|
1460
|
+
private readAutoSave;
|
|
1461
|
+
/**
|
|
1462
|
+
* The file that was kept (Auto save on), or the contact sample when none can be read; a file that was not saved after its last change comes back with its changes not saved, and with the file of the
|
|
1463
|
+
* project it belongs to.
|
|
1464
|
+
*/
|
|
1465
|
+
private restore;
|
|
1466
|
+
/** The editor starts with the contact sample (an empty file when there is none). */
|
|
1467
|
+
private startWithSample;
|
|
1468
|
+
/** The sample the editor started with while nothing else has come or been done: no editor of the application came back, Auto save brought nothing, nothing was changed. */
|
|
1469
|
+
private fresh;
|
|
1470
|
+
/**
|
|
1471
|
+
* Starts with another sample of File > Samples (the input `sample` of the editor: Gridify Designer gives one), and the status bar says where the help is. Only while the editor shows the sample it
|
|
1472
|
+
* started with and nothing was done: a form layout that came back, or one that was loaded or changed, stays.
|
|
1473
|
+
*/
|
|
1474
|
+
startWith(id: string): void;
|
|
1475
|
+
/** Auto save could not keep the text of the file (no room, or no storage): its changes are nowhere else, so leaving the page is asked about as without Auto save. */
|
|
1476
|
+
private notKept;
|
|
1477
|
+
/**
|
|
1478
|
+
* Keeps the text of the file, whether it is the one that was saved last (`modified`: it is not), and the file of the project it belongs to. When the browser does not keep it, `tell` says so
|
|
1479
|
+
* (once, not for every change).
|
|
1480
|
+
*/
|
|
1481
|
+
private saveText;
|
|
1482
|
+
private forgetText;
|
|
1483
|
+
say(text: string): void;
|
|
1484
|
+
warn(text: string, id?: string): void;
|
|
1485
|
+
/** Selects elements of the form that is edited (`[]` selects nothing: the Inspector shows the variant). An element in a layer or a page that is not shown is shown. */
|
|
1486
|
+
select(names: readonly string[], scope?: Scope): void;
|
|
1487
|
+
/** Adds an element to the selection or takes it out (Ctrl and a click). */
|
|
1488
|
+
toggle(name: string): void;
|
|
1489
|
+
/** Adds elements to the selection after what is selected (the rectangle of Shift or Ctrl and a drag), so the first selected element stays the one the others are lined up with. */
|
|
1490
|
+
addToSelection(names: readonly string[]): void;
|
|
1491
|
+
selectForm(name: string, scope?: Scope): void;
|
|
1492
|
+
/** Edit the layers… of the menus: the Inspector shows the form, whose row `layers` holds its groups of layers, and the status bar says how they are written. */
|
|
1493
|
+
editLayers(): void;
|
|
1494
|
+
/** The subform whose form was opened from the Editor: the form it stands in and its name, for the way back. */
|
|
1495
|
+
readonly openedFrom: _angular_core.WritableSignal<{
|
|
1496
|
+
readonly form: string;
|
|
1497
|
+
readonly name: string;
|
|
1498
|
+
} | null>;
|
|
1499
|
+
/** Opens the form a subform places (a double click on it in the Editor); the toolbar and Escape lead back. */
|
|
1500
|
+
openSubform(name: string): void;
|
|
1501
|
+
/** Back from the form of a subform to the form it stands in, with the subform selected. */
|
|
1502
|
+
back(): void;
|
|
1503
|
+
selectVariant(minWidth: number): void;
|
|
1504
|
+
selectFile(): void;
|
|
1505
|
+
/** Selects a column or a row of the variant (a click on its number): the Inspector shows its size. */
|
|
1506
|
+
selectTrack(track: TrackRef | null): void;
|
|
1507
|
+
/** All the elements the Editor draws in a list: the one given (the menu of empty cells: the list of those cells), else the list of the selected element, else the top of the form. */
|
|
1508
|
+
selectAll(list?: string | null): void;
|
|
1509
|
+
/** Shows the layers and the page an element is in, so the Editor draws it. */
|
|
1510
|
+
reveal(name: string): void;
|
|
1511
|
+
/** Chooses the active layer of a group of layers in the Editor and the Preview; the layer of new elements follows when it was a layer of that group. */
|
|
1512
|
+
setLayer(group: string, layer: string): void;
|
|
1513
|
+
/** The layer the elements that are added get (`''`: none). */
|
|
1514
|
+
setNewLayer(layer: string): void;
|
|
1515
|
+
/** Shows a page of a property sheet in the Editor and the Preview (`select`: and selects the page). */
|
|
1516
|
+
showPage(sheet: string, page: string, selectIt?: boolean): void;
|
|
1517
|
+
/** The width the Editor draws the variant at (`null`: Fit); the Editor keeps it within the widths of its slider. */
|
|
1518
|
+
setDesignWidth(width: number | null): void;
|
|
1519
|
+
setShowGrid(on: boolean): void;
|
|
1520
|
+
/** The width of the form in the Preview (`null`: Fit); the Preview keeps it from `minFormWidth` of the file up (without it from 120 px). */
|
|
1521
|
+
setPreviewWidth(width: number | null): void;
|
|
1522
|
+
/** The Preview takes the width of the Editor (`on`), or its own again: then it keeps the width it has (the Editor's), as a Fit that is turned off keeps the width. */
|
|
1523
|
+
setPreviewFollows(on: boolean): void;
|
|
1524
|
+
/** A problem of the list was opened: the form, the variant and the element it is about are selected. */
|
|
1525
|
+
openProblem(problem: EditorProblem): void;
|
|
1526
|
+
/** What a step works on (the form, the variant, the selected elements): steps of one kind on the same things in a row are one step of undo. */
|
|
1527
|
+
private stepKey;
|
|
1528
|
+
/** Makes the step of an operation: a refusal is told, a note is said, the elements it names are selected. Gives whether the file changed. */
|
|
1529
|
+
private run;
|
|
1530
|
+
/** The list a new element goes into when no place is given: the selected group (the page shown in a selected sheet), or the list of the selected element, or the top of the form. */
|
|
1531
|
+
private targetList;
|
|
1532
|
+
/** The page a property sheet shows in the Editor. */
|
|
1533
|
+
shownPageOf(sheet: string): string | null;
|
|
1534
|
+
/** The cells inside the frame of a list: the cells of the group without its edge cells (the grid for the top). */
|
|
1535
|
+
innerCells(parent: string | null): Cells | null;
|
|
1536
|
+
/**
|
|
1537
|
+
* How many columns the tabs at the side of a property sheet take: the library draws them as a bar as thick as a control (the text runs along a tab) with a little room, about 36 px of the
|
|
1538
|
+
* width the Editor draws at.
|
|
1539
|
+
*/
|
|
1540
|
+
tabColumns(placed: Placed | null): number;
|
|
1541
|
+
/**
|
|
1542
|
+
* Adds what a tool of the Toolbox makes: on the cells `at` of the grid into the list `parent` (an area drawn in the Editor: the tool takes it), or (without them) into the selected group or
|
|
1543
|
+
* the list of the selected element, under what is in it (a group that is full grows for it; at the top of the form the grid grows down). New elements get the
|
|
1544
|
+
* layer that is chosen for them.
|
|
1545
|
+
*/
|
|
1546
|
+
addTool(id: ToolId, at?: {
|
|
1547
|
+
parent: string | null;
|
|
1548
|
+
cells: Cells;
|
|
1549
|
+
} | null, subform?: string): void;
|
|
1550
|
+
/** Adds a tool from a cell of a list (a drop, the menu of an empty cell): in its own size where it is free, else in the nearest free cells (see `toolRoom`). */
|
|
1551
|
+
addToolAtCell(id: ToolId, parent: string | null, cell: {
|
|
1552
|
+
col: number;
|
|
1553
|
+
row: number;
|
|
1554
|
+
}, subform?: string): void;
|
|
1555
|
+
/** The cells of a list that are taken for the elements that are added (those of the layers they can be shown with). */
|
|
1556
|
+
private takenIn;
|
|
1557
|
+
/** The cells of the frame of a group at each edge (a title, the tabs of a sheet; none for a group without a frame and for a page). */
|
|
1558
|
+
insetsOf(name: string): Insets;
|
|
1559
|
+
/** The inside of a list (the cells of a group without its frame; the grid at the top): it may have no rows, when a group is not higher than its frame. */
|
|
1560
|
+
private insideOf;
|
|
1561
|
+
/**
|
|
1562
|
+
* Where a tool goes in a list: from a cell, on the cells there in its own size (kept inside the list) or, where those are taken, the nearest free ones (the same columns further down, then
|
|
1563
|
+
* the first free cells from that row on); without a cell (a click on the tool), under what is in the list, at its left edge. A group without room grows for it: `grow` rows go in at the
|
|
1564
|
+
* bottom of its inside, where the tool goes. At the top of the form it goes under what is there (the grid grows down). `null` when the list has no place.
|
|
1565
|
+
*/
|
|
1566
|
+
toolRoom(id: ToolId, parent: string | null, cell: {
|
|
1567
|
+
col: number;
|
|
1568
|
+
row: number;
|
|
1569
|
+
} | null, subform?: string): {
|
|
1570
|
+
cells: Cells;
|
|
1571
|
+
grow: number;
|
|
1572
|
+
} | null;
|
|
1573
|
+
/** Puts what a tool makes on cells of a list; a group grows first by `grow` rows at the bottom of its inside (where the cells are then). */
|
|
1574
|
+
private putTool;
|
|
1575
|
+
/** What the status bar says about the elements that were added (they are selected): their names, and what F2 does with them. */
|
|
1576
|
+
private addedText;
|
|
1577
|
+
/** The cells an element without a place takes from a cell of its list (a drop from the strip under the grid). */
|
|
1578
|
+
unplacedCells(name: string, cell: {
|
|
1579
|
+
col: number;
|
|
1580
|
+
row: number;
|
|
1581
|
+
}): Cells | null;
|
|
1582
|
+
private groupOfLayer;
|
|
1583
|
+
/** A label for the selected input: above it when the row above is free, else before it in its row, else in the first free cells. */
|
|
1584
|
+
addLabel(): void;
|
|
1585
|
+
/** A new page of the property sheet (the selected one, or the one the selected page is in), shown at once. */
|
|
1586
|
+
addPage(sheet: string): void;
|
|
1587
|
+
/**
|
|
1588
|
+
* Removes the selected elements from the form, with what is in them, in every variant (Delete, Remove from the form). A toast says from which variants and offers Undo; Shift+Delete
|
|
1589
|
+
* (`unplaceSelected`) only takes them out of the variant that is edited.
|
|
1590
|
+
*/
|
|
1591
|
+
removeSelected(): void;
|
|
1592
|
+
/** The toast that offers to undo the last removal, and the file the removal left: its Undo undoes that step only, and it goes when the file changes otherwise. */
|
|
1593
|
+
private removal;
|
|
1594
|
+
private undoRemoval;
|
|
1595
|
+
duplicateSelected(): void;
|
|
1596
|
+
copySelected(): boolean;
|
|
1597
|
+
cutSelected(): void;
|
|
1598
|
+
/** Puts what was copied into the selected group (or the list of the selected element): where it was when that is the list it came from and the cells are free, else in the nearest free room. */
|
|
1599
|
+
paste(at?: {
|
|
1600
|
+
parent: string | null;
|
|
1601
|
+
col: number;
|
|
1602
|
+
row: number;
|
|
1603
|
+
}): void;
|
|
1604
|
+
/** Moves the selected elements with the arrows (with Shift they stretch the selected element). */
|
|
1605
|
+
nudgeSelected(dCol: number, dRow: number): void;
|
|
1606
|
+
/** Makes the selected elements larger or smaller to the right and down by cells (Shift with an arrow): each of them, in one step. */
|
|
1607
|
+
growSelected(dCols: number, dRows: number): void;
|
|
1608
|
+
/** Lines up the selected elements with the first of them (the buttons of the Editor, the Arrange menu, Ctrl and an arrow): one step of undo; what stayed where it was is said. */
|
|
1609
|
+
alignSelected(how: AlignHow): void;
|
|
1610
|
+
/** Moves the selected element earlier or later in the order of the page (Alt with Up or Down). */
|
|
1611
|
+
reorderSelected(delta: number): void;
|
|
1612
|
+
/** Elements dragged to other cells (the Editor). */
|
|
1613
|
+
moveElements(moves: readonly Move[]): void;
|
|
1614
|
+
/** An element stretched by its handles (the Editor). */
|
|
1615
|
+
resize(name: string, cells: Cells): void;
|
|
1616
|
+
/** An element moved in the Outline: into another list, or to another place in its own. */
|
|
1617
|
+
moveInTree(name: string, parent: string | null, index: number): void;
|
|
1618
|
+
rename(name: string, next: string): boolean;
|
|
1619
|
+
/** The caption of a control in the Editor (a check box, a switch, a button): `preview.props.label`, which the Preview shows and the template of the Output writes; empty takes it out. */
|
|
1620
|
+
setCaption(name: string, text: string): void;
|
|
1621
|
+
/** What F2 edits in place: the selected element, or the field among a field and its label that were added together. */
|
|
1622
|
+
textTarget(): string | null;
|
|
1623
|
+
/**
|
|
1624
|
+
* Opens the field that edits a text in the Editor itself (F2, a double click, the menus): the text of a static, the title of a group or a page, the caption of a control (`caption`), or the
|
|
1625
|
+
* name. The Editor draws the field on the element, so an element it does not draw in the variant (one the variant does not place, or one in a group it does not place) is edited in the
|
|
1626
|
+
* Inspector: the status bar says so. Gives whether the field opens.
|
|
1627
|
+
*/
|
|
1628
|
+
editInPlace(name: string, caption?: boolean): boolean;
|
|
1629
|
+
/** The text of a static or the title of a group typed in the Editor itself (`=code` is code). */
|
|
1630
|
+
setText(name: string, text: string): void;
|
|
1631
|
+
wrapSelected(look: 'none' | 'group-box'): void;
|
|
1632
|
+
unwrapSelected(): void;
|
|
1633
|
+
/** Takes the selected elements out of the variant that is edited (Shift+Delete, Not placed in this variant): they stay in the form and wait in the strip under the grid. */
|
|
1634
|
+
unplaceSelected(): void;
|
|
1635
|
+
/** Gives elements without a place in the variant free cells (the strip under the grid, Place all). */
|
|
1636
|
+
placeUnplaced(names: readonly string[]): void;
|
|
1637
|
+
/** An element without a place dropped on cells of the grid (the strip under the grid). */
|
|
1638
|
+
placeAt(name: string, cells: Cells): void;
|
|
1639
|
+
/** A setting of the place of the selected element (align, justify, flow, tabs). */
|
|
1640
|
+
setPlaceSetting(name: string, key: 'align' | 'justify' | 'flow' | 'tabs', value: unknown): void;
|
|
1641
|
+
setElementProperty(name: string, key: string, value: unknown): void;
|
|
1642
|
+
/** The user changed a row of the Inspector. */
|
|
1643
|
+
changeRow(id: string, value: unknown): void;
|
|
1644
|
+
/** What the status bar says when a row that goes into the file when it is left did (its hint was there: Enter or Tab puts it into the file). */
|
|
1645
|
+
private rowDone;
|
|
1646
|
+
setTabOrderMode(on: boolean): void;
|
|
1647
|
+
/** A new round of the order of the page: no element is clicked yet, and the first click in a list is its number 1. */
|
|
1648
|
+
private newTabRound;
|
|
1649
|
+
/**
|
|
1650
|
+
* The round of the order of the page after a step of undo or redo, which may have taken clicks back: in order are the clicked elements that still stand at the start of their list, one after
|
|
1651
|
+
* another, and the next click in the list comes after them.
|
|
1652
|
+
*/
|
|
1653
|
+
private recountTabRound;
|
|
1654
|
+
/** In the mode of the order of the page: the element that is clicked comes next in its list. */
|
|
1655
|
+
clickInTabOrder(name: string): void;
|
|
1656
|
+
/** A new variant from a width, a copy of the one that is edited; it is edited then. */
|
|
1657
|
+
addVariant(minWidth: number): void;
|
|
1658
|
+
/**
|
|
1659
|
+
* Asks for a width of its own (Another width… of the menus of the variants) and adds a variant from it, a copy of the one that is edited. The field starts with the width the Editor is drawn at
|
|
1660
|
+
* when it is chosen inside the widths of the variant, else with the middle of them (a variant without an end: 160 px more than its `minWidth`), when the form has no variant from there yet.
|
|
1661
|
+
*/
|
|
1662
|
+
addVariantOfWidth(): Promise<void>;
|
|
1663
|
+
/** The widths offered for a new variant: the usual breakpoints that the form does not have yet. */
|
|
1664
|
+
readonly variantProposals: _angular_core.Signal<number[]>;
|
|
1665
|
+
removeVariant(): Promise<void>;
|
|
1666
|
+
/** Puts columns or rows in before the track `at`. When columns (or rows) are selected, the new ones are selected instead: the numbers of the others move. */
|
|
1667
|
+
insertTrack(axis: 'col' | 'row', at: number, count?: number): void;
|
|
1668
|
+
deleteTrack(axis: 'col' | 'row', at: number): void;
|
|
1669
|
+
/** Takes the columns or the rows out (the menu of the numbers, for all the selected ones). */
|
|
1670
|
+
deleteTracks(axis: 'col' | 'row', indices: readonly number[]): void;
|
|
1671
|
+
/** Gives one size to columns or rows (`null`: the size of the others, 1fr or a row of the grid). */
|
|
1672
|
+
setTrackSizes(axis: 'col' | 'row', indices: readonly number[], size: string | null): void;
|
|
1673
|
+
/** The columns that the selected elements stand on in the variant that is edited (the numbers from 1, in order). */
|
|
1674
|
+
columnsOfSelection(): number[];
|
|
1675
|
+
/**
|
|
1676
|
+
* Keep their width (the menu of an element): the columns of the selected elements get the width they have now in the Editor, in whole px, so the elements keep their width when the form is wider
|
|
1677
|
+
* or narrower (a label stays beside its field). A column that has a size in px keeps it.
|
|
1678
|
+
*/
|
|
1679
|
+
keepColumnWidths(columns?: readonly number[]): void;
|
|
1680
|
+
/** Share the width (the menu of an element): the columns of the selected elements are 1fr again, a share of the width as the other columns. */
|
|
1681
|
+
shareColumnWidths(): void;
|
|
1682
|
+
/** Select them (the menu of an element): the columns of the selected elements are selected, and the Inspector has their size. */
|
|
1683
|
+
selectColumnsOfSelection(): void;
|
|
1684
|
+
/** Makes the grid of the variant longer or shorter by rows at the bottom (the handle under the grid). */
|
|
1685
|
+
setRows(rows: number): void;
|
|
1686
|
+
/** The empty rows and columns at the edges of the variant that is edited (the menus of the cells and of the variant trim them). */
|
|
1687
|
+
readonly emptyEdges: _angular_core.Signal<EmptyEdges>;
|
|
1688
|
+
/** Takes the empty rows or columns at the edges of the variant away: at the start (the top, the left), at the end (the bottom, the right), or at both. */
|
|
1689
|
+
trimEdges(axis: 'col' | 'row', start: boolean, end: boolean): void;
|
|
1690
|
+
addForm(): void;
|
|
1691
|
+
removeForm(name: string): Promise<void>;
|
|
1692
|
+
/** A copy of a form after it, under a free name: the copy is selected, and the status bar names it. */
|
|
1693
|
+
duplicateForm(name: string): void;
|
|
1694
|
+
moveForm(name: string, delta: number): void;
|
|
1695
|
+
undo(): void;
|
|
1696
|
+
redo(): void;
|
|
1697
|
+
/** A step of undo or redo: the form and the variant it changed are shown, with the elements whose places it changed selected, so the user sees what came back. */
|
|
1698
|
+
private step;
|
|
1699
|
+
private mayReplace;
|
|
1700
|
+
newFile(): Promise<void>;
|
|
1701
|
+
loadSample(id: string): Promise<void>;
|
|
1702
|
+
/**
|
|
1703
|
+
* A text from outside (a file, the clipboard, a drop) replaces the document; a text that is not a form layout is not loaded, and the user is told where it goes wrong. Gives whether the text was loaded
|
|
1704
|
+
* (the user may also keep the file that was changed). `name` is what the messages call it, `origin` where it came from (by default a file of that name), for the title in the menu bar.
|
|
1705
|
+
*/
|
|
1706
|
+
loadFromText(text: string, name: string, origin?: DocumentOrigin): Promise<boolean>;
|
|
1707
|
+
openFile(): void;
|
|
1708
|
+
/** File > Open from the project…: a file of the project replaces the document (as a file of the computer does), and the document belongs to it then: Save writes it back there. */
|
|
1709
|
+
openFromProject(): Promise<void>;
|
|
1710
|
+
/** File > Save: the file goes back into the file of the project that it belongs to (a document that belongs to none asks where, as Save as… does). It is saved then, as after a download. */
|
|
1711
|
+
saveToProject(): Promise<void>;
|
|
1712
|
+
/** File > Save as…: the file goes into a file of the project that the user chooses, and belongs to it from then on. */
|
|
1713
|
+
saveToProjectAs(): Promise<void>;
|
|
1714
|
+
pasteFile(): Promise<void>;
|
|
1715
|
+
copyOutput(): Promise<void>;
|
|
1716
|
+
/** The name the file is downloaded under (and Save as… proposes): the first form's. */
|
|
1717
|
+
private fileName;
|
|
1718
|
+
/** Offers the file for download. It is saved then (not modified until the next change), unless it belongs to a file of the project: then the download is a copy, and the file is saved by Save. */
|
|
1719
|
+
downloadFile(): void;
|
|
1720
|
+
private downloaded;
|
|
1721
|
+
downloadOutput(): void;
|
|
1722
|
+
/** Where the selection is, for the status bar. */
|
|
1723
|
+
readonly where: _angular_core.Signal<string>;
|
|
1724
|
+
/**
|
|
1725
|
+
* The elements that are shown and that some cells touch, in the order of the page: what the menu of an area drawn on the grid selects (Select these), and what the rectangle of Shift or Ctrl
|
|
1726
|
+
* and a drag adds. A piece of an element is enough, and of a group too: a group that the cells touch is taken whole, and then what is in it goes with it (the group is named, not its
|
|
1727
|
+
* elements, so they move together). Only cells that lie in a group, and are less than all of it, take what they touch in it and not the group: a rectangle drawn in a group.
|
|
1728
|
+
*/
|
|
1729
|
+
elementsIn(cells: Cells): string[];
|
|
1730
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<FormEditorStore, never>;
|
|
1731
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<FormEditorStore>;
|
|
1732
|
+
}
|
|
1733
|
+
|
|
1734
|
+
/**
|
|
1735
|
+
* The editor of form layouts (`"format": "gfy-form-layout"`): the forms of a file, the elements of each form (texts, places for the controls of an application, groups, subforms) and the variants
|
|
1736
|
+
* that give them their places in cells for the widths from a `minWidth` up. The grid of a variant is edited in the Editor window as `<gfy-form>` lays it out, the Preview shows the form working,
|
|
1737
|
+
* and the file goes to the application (the Output window has the template and a component that loads it). The state is in `FormEditorStore`, which this component provides, and the windows only
|
|
1738
|
+
* read it and call its commands. An application that gives it the files of a project (`files`) gets File > Open from the project…, Save and Save as… besides. The editor is English only.
|
|
1739
|
+
*/
|
|
1740
|
+
declare class FormEditor implements OnInit {
|
|
1741
|
+
/** The editor is shown by an application with its own header (the one that switches between the editors): it leaves its name and the choice of the theme out, and fills the place it is given. */
|
|
1742
|
+
readonly hosted: _angular_core.InputSignalWithTransform<boolean, unknown>;
|
|
1743
|
+
/**
|
|
1744
|
+
* The files of a project (a folder of the computer, a server, a place of the application: see `GfyEditorFiles`): File > Open from the project… opens a form layout of the project, Save writes it back
|
|
1745
|
+
* (when the file is still the one that was opened), Save as… writes it under another name. Without them (the default) the editor opens a file of the computer and offers the file for download, as it
|
|
1746
|
+
* always did.
|
|
1747
|
+
*/
|
|
1748
|
+
readonly files: _angular_core.InputSignal<GfyEditorFiles | null>;
|
|
1749
|
+
/**
|
|
1750
|
+
* The id of a sample of File > Samples that the editor starts with when it has nothing else to show (no form layout that the application left in it, nothing that Auto save kept). Without it the
|
|
1751
|
+
* editor starts with the contact form; Gridify Designer gives `contact`. A form layout that came back stays.
|
|
1752
|
+
*/
|
|
1753
|
+
readonly sample: _angular_core.InputSignal<string | null>;
|
|
1754
|
+
protected readonly store: FormEditorStore;
|
|
1755
|
+
/** The Help menu and its window (it closes with the editor). */
|
|
1756
|
+
private readonly help;
|
|
1757
|
+
private readonly engine;
|
|
1758
|
+
protected readonly layout: GfyDockContainerNodeInput;
|
|
1759
|
+
protected readonly windowsKey = "gfy-form-editor:windows";
|
|
1760
|
+
constructor();
|
|
1761
|
+
/** The sample to start with is an input, so it is known only now (the store started before it). */
|
|
1762
|
+
ngOnInit(): void;
|
|
1763
|
+
protected saveWindows(): void;
|
|
1764
|
+
/**
|
|
1765
|
+
* The windows of the View menu: each one checked while it is open (docked or floating), and a click closes an open one or opens a closed one again at its place (the View menu of the engine,
|
|
1766
|
+
* `GfyViewTabs`, which follows the tabs as they open and close).
|
|
1767
|
+
*/
|
|
1768
|
+
private windowItems;
|
|
1769
|
+
private resetWindows;
|
|
1770
|
+
protected readonly menus: _angular_core.Signal<GfyMenu[]>;
|
|
1771
|
+
/** The title of the document in the menu bar: its file of the project, or where it came from (a new one, a sample, a file of the computer, the clipboard), with a dot while it has changes. */
|
|
1772
|
+
protected readonly title: _angular_core.Signal<DocumentTitle>;
|
|
1773
|
+
protected readonly statusItems: _angular_core.Signal<GfyStatusItem[]>;
|
|
1774
|
+
protected onFileDragOver(event: DragEvent): void;
|
|
1775
|
+
protected onFileDrop(event: DragEvent): void;
|
|
1776
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<FormEditor, never>;
|
|
1777
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<FormEditor, "form-editor", never, { "hosted": { "alias": "hosted"; "required": false; "isSignal": true; }; "files": { "alias": "files"; "required": false; "isSignal": true; }; "sample": { "alias": "sample"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
1778
|
+
}
|
|
1779
|
+
|
|
1780
|
+
export { FormEditor, GfyEditorFileConflict, LayoutEditor, RibbonEditor, gfyHttpFiles, gfyLocalFolderFiles, gfyLocalFolderSupported, gfyPickLocalFolder };
|
|
1781
|
+
export type { GfyEditorFile, GfyEditorFileEntry, GfyEditorFiles, GfyEditorWriteCondition, GfyHttpFilesOptions, GfyLocalFolderOptions };
|