@navette-js/forms 1.0.0-beta.2 → 1.0.0-beta.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/builder.d.ts +45 -4
- package/lib/builder.js +99 -16
- package/lib/index.d.ts +722 -68
- package/lib/index.js +1705 -234
- package/lib/rules.d.ts +19 -0
- package/lib/rules.js +148 -0
- package/package.json +4 -4
- package/views/components/text-input.ejs +14 -5
package/lib/index.d.ts
CHANGED
|
@@ -2,11 +2,8 @@ import { HtmlString, type ColorManager, type Lazy } from '@navette-js/support';
|
|
|
2
2
|
import { Component, Schema, type ComponentContext } from '@navette-js/schemas';
|
|
3
3
|
import { Action } from '@navette-js/actions';
|
|
4
4
|
export declare const useColorManager: (manager: ColorManager) => void;
|
|
5
|
-
type Rule
|
|
6
|
-
|
|
7
|
-
passes: (value: unknown, ctx: ComponentContext) => boolean | Promise<boolean>;
|
|
8
|
-
message: (attribute: string) => string;
|
|
9
|
-
};
|
|
5
|
+
import { type Rule } from './rules.ts';
|
|
6
|
+
export type { Rule } from './rules.ts';
|
|
10
7
|
export declare abstract class Field extends Component {
|
|
11
8
|
protected _label: Lazy<string | null, ComponentContext>;
|
|
12
9
|
protected _required: Lazy<boolean, ComponentContext>;
|
|
@@ -20,7 +17,18 @@ export declare abstract class Field extends Component {
|
|
|
20
17
|
protected _dehydrated: boolean | null;
|
|
21
18
|
protected _hiddenLabel: boolean;
|
|
22
19
|
protected _helperText: string | null;
|
|
20
|
+
protected _liveMode: 'live' | 'blur' | null;
|
|
21
|
+
protected _validationAttribute: string | null;
|
|
22
|
+
protected _validationMessages: Record<string, string | ((attribute: string) => string)>;
|
|
23
|
+
protected _markedAsRequired: boolean | null;
|
|
23
24
|
constructor(name: string);
|
|
25
|
+
/** Sends the state to the server as soon as it changes (`onBlur`: when the field loses focus). `false` turns it off. */
|
|
26
|
+
live(condition?: boolean | {
|
|
27
|
+
onBlur?: boolean;
|
|
28
|
+
}): this;
|
|
29
|
+
isLive(): boolean;
|
|
30
|
+
/** `wire:model` directive of the field, with its live modifiers. */
|
|
31
|
+
protected wireModel(): string;
|
|
24
32
|
hasStatePath(): boolean;
|
|
25
33
|
getName(): string;
|
|
26
34
|
getId(): string;
|
|
@@ -71,7 +79,100 @@ export declare abstract class Field extends Component {
|
|
|
71
79
|
getDefaultState(): unknown;
|
|
72
80
|
/** Shapes a record value as it enters the form (hydration). */
|
|
73
81
|
hydrateState(value: unknown): unknown;
|
|
74
|
-
rule(
|
|
82
|
+
/** Adds a rule: an object `{ name, passes, message }`, or a Laravel-style string (`'max:255'`, `'regex:/^[a-z]+$/'`). */
|
|
83
|
+
rule(rule: Rule | string, condition?: boolean | ((ctx: ComponentContext) => boolean | Promise<boolean>)): this;
|
|
84
|
+
/** Several rules at once: `rules(['required', 'max:255'])` or `rules('required|max:255')`. */
|
|
85
|
+
rules(rules: (Rule | string)[] | string, condition?: boolean | ((ctx: ComponentContext) => boolean | Promise<boolean>)): this;
|
|
86
|
+
/** Value checked by the rules (a subclass may trim it, for instance). */
|
|
87
|
+
protected stateForValidation(state: unknown): unknown;
|
|
88
|
+
/** Sizes (`min`, `max`, `size`, `between`) compare the number, not the text length. */
|
|
89
|
+
protected hasNumericValidation(): boolean;
|
|
90
|
+
/** Name of the field in validation messages (the lowercased label by default). */
|
|
91
|
+
validationAttribute(name: string | null): this;
|
|
92
|
+
/** Custom messages by rule name (`{ required: 'Tell us your name.', max: 'Too long.' }`); `:attribute` is replaced by the field name. */
|
|
93
|
+
validationMessages(messages: Record<string, string | ((attribute: string) => string)>): this;
|
|
94
|
+
protected _loadStateFromRelationships: ((record: any, ctx: ComponentContext) => unknown) | null;
|
|
95
|
+
protected _saveRelationships: ((args: {
|
|
96
|
+
record: any;
|
|
97
|
+
state: unknown;
|
|
98
|
+
ctx: ComponentContext;
|
|
99
|
+
}) => void | Promise<void>) | null;
|
|
100
|
+
/** Fills the field from the record's relationships (after the record's own values): `(record, ctx) => state`. */
|
|
101
|
+
loadStateFromRelationshipsUsing(callback: ((record: any, ctx: ComponentContext) => unknown) | null): this;
|
|
102
|
+
/** Saves the field into the record's relationships, once the record is created or updated. Such a field is not in the saved data. */
|
|
103
|
+
saveRelationshipsUsing(callback: ((args: {
|
|
104
|
+
record: any;
|
|
105
|
+
state: unknown;
|
|
106
|
+
ctx: ComponentContext;
|
|
107
|
+
}) => void | Promise<void>) | null): this;
|
|
108
|
+
/** Whether the field saves itself through `saveRelationshipsUsing()` (and is then left out of the saved data). */
|
|
109
|
+
savesRelationships(): Promise<boolean>;
|
|
110
|
+
loadStateFromRelationships(record: any): Promise<{
|
|
111
|
+
state: unknown;
|
|
112
|
+
} | null>;
|
|
113
|
+
saveRelationships(record: any): Promise<void>;
|
|
114
|
+
/** Shows (or hides, with `false`) the required asterisk, regardless of `required()`. */
|
|
115
|
+
markAsRequired(condition?: boolean): this;
|
|
116
|
+
isMarkedAsRequired(): Promise<boolean>;
|
|
117
|
+
private stringRuleWith;
|
|
118
|
+
/** The value must match the pattern (a RegExp, or a `/pattern/flags` string). */
|
|
119
|
+
regex(pattern: RegExp | string): this;
|
|
120
|
+
notRegex(pattern: RegExp | string): this;
|
|
121
|
+
alpha(): this;
|
|
122
|
+
alphaDash(): this;
|
|
123
|
+
alphaNum(): this;
|
|
124
|
+
ascii(): this;
|
|
125
|
+
uuid(): this;
|
|
126
|
+
ulid(): this;
|
|
127
|
+
json(): this;
|
|
128
|
+
ip(): this;
|
|
129
|
+
ipv4(): this;
|
|
130
|
+
ipv6(): this;
|
|
131
|
+
macAddress(): this;
|
|
132
|
+
hexColor(): this;
|
|
133
|
+
multipleOf(value: number): this;
|
|
134
|
+
/** The value must be one of these (a list, or the values of an enum-like object). */
|
|
135
|
+
in(values: readonly (string | number)[] | Record<string, string | number>): this;
|
|
136
|
+
notIn(values: readonly (string | number)[]): this;
|
|
137
|
+
/** `in()` with the values of an enum-like object. */
|
|
138
|
+
enum(values: Record<string, string | number>): this;
|
|
139
|
+
startsWith(prefixes: string | string[]): this;
|
|
140
|
+
endsWith(suffixes: string | string[]): this;
|
|
141
|
+
doesntStartWith(prefixes: string | string[]): this;
|
|
142
|
+
doesntEndWith(suffixes: string | string[]): this;
|
|
143
|
+
/** The field must equal `<name>_confirmation` (or the given field) of the same form. */
|
|
144
|
+
confirmed(field?: string | null): this;
|
|
145
|
+
same(field: string): this;
|
|
146
|
+
different(field: string): this;
|
|
147
|
+
/** Compares with a number or another field of the same form. */
|
|
148
|
+
gt(fieldOrValue: string | number): this;
|
|
149
|
+
gte(fieldOrValue: string | number): this;
|
|
150
|
+
lt(fieldOrValue: string | number): this;
|
|
151
|
+
lte(fieldOrValue: string | number): this;
|
|
152
|
+
/** No duplicates in a list value (tags, multiple select, checkbox list). */
|
|
153
|
+
distinct(): this;
|
|
154
|
+
/** Required when another field of the form has one of these values (`requiredIf('type', 'company')`). */
|
|
155
|
+
requiredIf(field: string, values: unknown): this;
|
|
156
|
+
requiredUnless(field: string, values: unknown): this;
|
|
157
|
+
requiredIfAccepted(field: string): this;
|
|
158
|
+
requiredWith(fields: string | string[]): this;
|
|
159
|
+
requiredWithAll(fields: string | string[]): this;
|
|
160
|
+
requiredWithout(fields: string | string[]): this;
|
|
161
|
+
requiredWithoutAll(fields: string | string[]): this;
|
|
162
|
+
prohibited(condition?: boolean): this;
|
|
163
|
+
prohibitedIf(field: string, values: unknown): this;
|
|
164
|
+
prohibitedUnless(field: string, values: unknown): this;
|
|
165
|
+
prohibits(fields: string | string[]): this;
|
|
166
|
+
/**
|
|
167
|
+
* The value must exist: in a column of the host's data adapter (`exists()`, `exists({ column })`), in another adapter
|
|
168
|
+
* (`exists({ adapter: new ObjectionAdapter(Brand), column: 'id' })`), or according to a function.
|
|
169
|
+
*/
|
|
170
|
+
exists(check?: {
|
|
171
|
+
adapter?: {
|
|
172
|
+
exists(column: string, value: unknown, exceptKey?: string | number | null): Promise<boolean>;
|
|
173
|
+
};
|
|
174
|
+
column?: string;
|
|
175
|
+
} | ((value: unknown, ctx: ComponentContext) => boolean | Promise<boolean>)): this;
|
|
75
176
|
/** `unique` rule: the value must not exist in the column of the same name; `ignoreRecord` excludes the record being edited. */
|
|
76
177
|
unique(options?: {
|
|
77
178
|
ignoreRecord?: boolean;
|
|
@@ -111,6 +212,7 @@ export declare class TextInput extends Field {
|
|
|
111
212
|
private _prefix;
|
|
112
213
|
private _live;
|
|
113
214
|
static make(name: string): TextInput;
|
|
215
|
+
protected hasNumericValidation(): boolean;
|
|
114
216
|
/** Decimal number: `type="number"`, `step="any"`. */
|
|
115
217
|
numeric(): this;
|
|
116
218
|
/** Integer: `type="number"`, `step="1"`. */
|
|
@@ -120,11 +222,57 @@ export declare class TextInput extends Field {
|
|
|
120
222
|
step(step: number | 'any' | null): this;
|
|
121
223
|
minValue(value: number): this;
|
|
122
224
|
maxValue(value: number): this;
|
|
123
|
-
/** Label shown before the input (e.g. `$`). */
|
|
124
|
-
prefix(label: string | null): this;
|
|
225
|
+
/** Label shown before the input (e.g. `$`); `isInline`: inside the input instead of a separate box. */
|
|
226
|
+
prefix(label: string | null, isInline?: boolean): this;
|
|
125
227
|
private _suffix;
|
|
126
228
|
/** Label shown after the input ("hours", "kg"…). */
|
|
127
|
-
suffix(label: string | null): this;
|
|
229
|
+
suffix(label: string | null, isInline?: boolean): this;
|
|
230
|
+
private _prefixInline;
|
|
231
|
+
private _suffixInline;
|
|
232
|
+
private _prefixIcon;
|
|
233
|
+
private _suffixIcon;
|
|
234
|
+
private _prefixIconColor;
|
|
235
|
+
private _suffixIconColor;
|
|
236
|
+
private _prefixActions;
|
|
237
|
+
private _suffixActions;
|
|
238
|
+
prefixIcon(icon: string | null, isInline?: boolean): this;
|
|
239
|
+
suffixIcon(icon: string | null, isInline?: boolean): this;
|
|
240
|
+
prefixIconColor(color: string | null): this;
|
|
241
|
+
suffixIconColor(color: string | null): this;
|
|
242
|
+
/**
|
|
243
|
+
* Icon button before the input, running an action. The action gets the field's `state`, and `set(name, value)` to change a
|
|
244
|
+
* field of the same form.
|
|
245
|
+
*/
|
|
246
|
+
prefixAction(action: Action, isInline?: boolean): this;
|
|
247
|
+
prefixActions(actions: Action[]): this;
|
|
248
|
+
suffixAction(action: Action, isInline?: boolean): this;
|
|
249
|
+
suffixActions(actions: Action[]): this;
|
|
250
|
+
/** Affix actions, mounted through the schema component. */
|
|
251
|
+
getActions(): Action[];
|
|
252
|
+
/** Exact length: `minlength` and `maxlength`, and the matching rule. */
|
|
253
|
+
length(length: number): this;
|
|
254
|
+
private _datalist;
|
|
255
|
+
/** Suggestions offered by the browser while typing (`<datalist>`). */
|
|
256
|
+
datalist(options: string[]): this;
|
|
257
|
+
private _readOnly;
|
|
258
|
+
/** The value is shown and sent, but cannot be changed (`readonly`). */
|
|
259
|
+
readOnly(condition?: boolean): this;
|
|
260
|
+
private _copyable;
|
|
261
|
+
/** A button after the input copies its value (the browser only allows it on HTTPS or `localhost`). */
|
|
262
|
+
copyable(condition?: boolean, copyMessage?: string | null, copyMessageDuration?: number): this;
|
|
263
|
+
private _trim;
|
|
264
|
+
/** Removes the spaces around the value before it is validated and saved. */
|
|
265
|
+
trim(condition?: boolean): this;
|
|
266
|
+
hydrateState(value: unknown): unknown;
|
|
267
|
+
/** `trim()`: the submitted value is trimmed before it is validated and saved. */
|
|
268
|
+
protected stateForValidation(state: unknown): unknown;
|
|
269
|
+
dehydrateState(state: unknown): unknown;
|
|
270
|
+
private _inputMode;
|
|
271
|
+
private _autocapitalize;
|
|
272
|
+
/** Virtual keyboard: `none`, `text`, `decimal`, `numeric`, `tel`, `search`, `email` or `url`. */
|
|
273
|
+
inputMode(mode: string | null): this;
|
|
274
|
+
/** `none`, `sentences`, `words` or `characters` (`true` / `false` for `on` / `off`). */
|
|
275
|
+
autocapitalize(mode?: string | boolean | null): this;
|
|
128
276
|
/** Sends the state to the server on every keystroke, or on blur with `onBlur`. */
|
|
129
277
|
live(options?: {
|
|
130
278
|
onBlur?: boolean;
|
|
@@ -140,33 +288,25 @@ export declare class TextInput extends Field {
|
|
|
140
288
|
mask(pattern: string | null): this;
|
|
141
289
|
/** Phone number: digits, spaces and common punctuation. */
|
|
142
290
|
tel(): this;
|
|
291
|
+
email(condition?: boolean): this;
|
|
143
292
|
/** Web address: `url` input type, a valid http(s) value is required. */
|
|
144
293
|
url(): this;
|
|
145
294
|
maxLength(length: number): this;
|
|
146
295
|
minLength(length: number): this;
|
|
147
296
|
toHtml(): Promise<string>;
|
|
148
297
|
}
|
|
149
|
-
/** Native date picker (`<input type="date">`). */
|
|
150
|
-
export declare class DatePicker extends Field {
|
|
151
|
-
private _maxDate;
|
|
152
|
-
private _minDate;
|
|
153
|
-
private _live;
|
|
154
|
-
static make(name: string): DatePicker;
|
|
155
|
-
private _datePlaceholder;
|
|
156
|
-
/** Placeholder attribute (browsers do not display it on a native `date` input). */
|
|
157
|
-
placeholder(text: string | null): this;
|
|
158
|
-
/** Sends the state to the server as soon as it changes (`wire:model.live`). */
|
|
159
|
-
live(condition?: boolean): this;
|
|
160
|
-
/** The state is a `YYYY-MM-DD` date, whatever the stored precision. */
|
|
161
|
-
hydrateState(value: unknown): unknown;
|
|
162
|
-
private static resolve;
|
|
163
|
-
private bound;
|
|
164
|
-
/** Latest accepted date: `'today'`, a `YYYY-MM-DD` date, or a context function (`({ get }) => get('endDate') || 'today'`). */
|
|
165
|
-
maxDate(date: Lazy<string | null, ComponentContext>): this;
|
|
166
|
-
minDate(date: Lazy<string | null, ComponentContext>): this;
|
|
167
|
-
toHtml(): Promise<string>;
|
|
168
|
-
}
|
|
169
298
|
type Options = [string, string][] | Record<string, string>;
|
|
299
|
+
/** Options, possibly grouped: `{ 'In process': { draft: 'Draft', reviewing: 'Reviewing' }, Reviewed: { … } }`. */
|
|
300
|
+
type GroupedOptions = Options | Record<string, string | Record<string, string>> | [string, string | [string, string][]][];
|
|
301
|
+
type OptionGroup = {
|
|
302
|
+
label: string;
|
|
303
|
+
options: [string, string][];
|
|
304
|
+
};
|
|
305
|
+
/**
|
|
306
|
+
* Copy of a component and of the components it holds (layout children, item schemas), so that each repeated item gets its own
|
|
307
|
+
* instances: components keep a reference to their container.
|
|
308
|
+
*/
|
|
309
|
+
export declare function cloneComponentTree<T extends Component>(component: T): T;
|
|
170
310
|
/**
|
|
171
311
|
* Dropdown. Native (`<select>`) by default; `searchable()` switches to the JavaScript select,
|
|
172
312
|
* which queries the server through the exposed methods (`getSearchResultsForJs`…).
|
|
@@ -175,6 +315,15 @@ export declare class Select extends Field {
|
|
|
175
315
|
private _options;
|
|
176
316
|
private _placeholder;
|
|
177
317
|
private _searchable;
|
|
318
|
+
private _native;
|
|
319
|
+
private _allowHtml;
|
|
320
|
+
private _maxItems;
|
|
321
|
+
private _minItems;
|
|
322
|
+
private _optionsLimit;
|
|
323
|
+
private _searchDebounce;
|
|
324
|
+
private _messages;
|
|
325
|
+
private _relationship;
|
|
326
|
+
private _affixes;
|
|
178
327
|
private _dynamic;
|
|
179
328
|
private _searchOnServer;
|
|
180
329
|
private _live;
|
|
@@ -194,10 +343,55 @@ export declare class Select extends Field {
|
|
|
194
343
|
* `dynamic: false`: options come from a function but stay fixed for the page's lifetime (announced as static to the browser).
|
|
195
344
|
* `searchOnServer: false`: search runs in the browser, among the options already sent (for a complete list).
|
|
196
345
|
*/
|
|
197
|
-
options(options:
|
|
346
|
+
options(options: GroupedOptions | ((ctx: ComponentContext) => GroupedOptions | Promise<GroupedOptions>), config?: {
|
|
198
347
|
dynamic?: boolean;
|
|
199
348
|
searchOnServer?: boolean;
|
|
200
349
|
}): this;
|
|
350
|
+
/** "Yes" / "No" options, saved as `1` / `0`. */
|
|
351
|
+
boolean(trueLabel?: string | null, falseLabel?: string | null, placeholder?: string | null): this;
|
|
352
|
+
/** `false`: the JavaScript select, even without search. */
|
|
353
|
+
native(condition?: boolean): this;
|
|
354
|
+
/** Option labels are HTML (sanitized on the server; JavaScript select only). */
|
|
355
|
+
allowHtml(condition?: boolean): this;
|
|
356
|
+
/** Maximum (and minimum) number of selected items of a multiple select, checked on the server. */
|
|
357
|
+
maxItems(count: number | null): this;
|
|
358
|
+
minItems(count: number | null): this;
|
|
359
|
+
/** Number of options shown at once in the JavaScript select (50 by default). */
|
|
360
|
+
optionsLimit(limit: number): this;
|
|
361
|
+
searchDebounce(ms: number): this;
|
|
362
|
+
loadingMessage(message: string): this;
|
|
363
|
+
noSearchResultsMessage(message: string): this;
|
|
364
|
+
searchPrompt(message: string): this;
|
|
365
|
+
searchingMessage(message: string): this;
|
|
366
|
+
noOptionsMessage(message: string): this;
|
|
367
|
+
prefix(label: string | null, isInline?: boolean): this;
|
|
368
|
+
suffix(label: string | null, isInline?: boolean): this;
|
|
369
|
+
prefixIcon(name: string | null, isInline?: boolean): this;
|
|
370
|
+
suffixIcon(name: string | null, isInline?: boolean): this;
|
|
371
|
+
prefixIconColor(color: string | null): this;
|
|
372
|
+
suffixIconColor(color: string | null): this;
|
|
373
|
+
prefixAction(action: Action, isInline?: boolean): this;
|
|
374
|
+
suffixAction(action: Action, isInline?: boolean): this;
|
|
375
|
+
prefixActions(actions: Action[]): this;
|
|
376
|
+
suffixActions(actions: Action[]): this;
|
|
377
|
+
/**
|
|
378
|
+
* Options from a relationship of the form's model (Objection `relationMappings`): a belongs-to relationship (the field is the
|
|
379
|
+
* foreign key, `Select.make('author_id').relationship('author', 'name')`), or a many-to-many one with `multiple()` (the field is
|
|
380
|
+
* named after the relationship, and saves the links once the record is saved). `modifyQueryUsing(query, search)` scopes the
|
|
381
|
+
* options; picked keys outside that scope are rejected. With `searchable()`, the options are searched on the server.
|
|
382
|
+
*/
|
|
383
|
+
relationship(name: string, titleAttribute?: string | null, modifyQueryUsing?: ((query: any, search?: string) => unknown) | null, options?: {
|
|
384
|
+
model?: any;
|
|
385
|
+
}): this;
|
|
386
|
+
private relationInfo;
|
|
387
|
+
private relationshipOptions;
|
|
388
|
+
private isManyRelationship;
|
|
389
|
+
savesRelationships(): Promise<boolean>;
|
|
390
|
+
loadStateFromRelationships(record: any): Promise<{
|
|
391
|
+
state: unknown;
|
|
392
|
+
} | null>;
|
|
393
|
+
/** Many-to-many: links the picked records and unlinks the others (only keys allowed by the relationship's query). */
|
|
394
|
+
saveRelationships(record: any): Promise<void>;
|
|
201
395
|
/** Disables an option depending on the context (e.g. already picked in another row). */
|
|
202
396
|
disableOptionWhen(condition: (value: string, ctx: ComponentContext) => boolean): this;
|
|
203
397
|
/** Sends the state to the server as soon as it changes. */
|
|
@@ -216,19 +410,20 @@ export declare class Select extends Field {
|
|
|
216
410
|
/** Sanitized selected values: unique strings. */
|
|
217
411
|
private selectedValues;
|
|
218
412
|
private labelsOf;
|
|
219
|
-
|
|
220
|
-
|
|
413
|
+
private _preload;
|
|
414
|
+
/** Relationship with `searchable()`: loads the options with the form, instead of on search only. Other options are always loaded. */
|
|
415
|
+
preload(condition?: boolean): this;
|
|
221
416
|
hydrateState(value: unknown): unknown;
|
|
222
417
|
dehydrateState(state: unknown): unknown;
|
|
418
|
+
/** Options with their groups (labels sanitized when `allowHtml()`). */
|
|
419
|
+
resolveGroupedOptions(): Promise<(OptionGroup | [string, string])[]>;
|
|
223
420
|
resolveOptions(): Promise<[string, string][]>;
|
|
421
|
+
private itemCountRules;
|
|
224
422
|
getValidationRules(): Promise<Rule[]>;
|
|
225
423
|
getExposedMethods(): string[];
|
|
226
424
|
private static forJs;
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
value: string;
|
|
230
|
-
isDisabled: boolean;
|
|
231
|
-
}[]>;
|
|
425
|
+
private groupsForJs;
|
|
426
|
+
getOptionsForJs(): Promise<unknown[]>;
|
|
232
427
|
private withDisabled;
|
|
233
428
|
getSearchResultsForJs(search?: unknown): Promise<{
|
|
234
429
|
label: string;
|
|
@@ -274,7 +469,10 @@ export declare class Select extends Field {
|
|
|
274
469
|
private getEditOptionAction;
|
|
275
470
|
/** Actions mounted on the field: hint, create option and edit option. */
|
|
276
471
|
getActions(): Action[];
|
|
277
|
-
|
|
472
|
+
private affixIcon;
|
|
473
|
+
private affixActionsHtml;
|
|
474
|
+
private prefixHtml;
|
|
475
|
+
/** Suffix: label, icon, actions, then the "+" and "edit" buttons. */
|
|
278
476
|
private suffixHtml;
|
|
279
477
|
toHtml(): Promise<string>;
|
|
280
478
|
/** JavaScript select rendering. */
|
|
@@ -295,59 +493,221 @@ type ItemLink = {
|
|
|
295
493
|
url: string;
|
|
296
494
|
};
|
|
297
495
|
/**
|
|
298
|
-
* List of repeated items sharing the same fields
|
|
496
|
+
* List of repeated items sharing the same fields: stacked cards (default), a table (`table()`), or one field per item (`simple()`).
|
|
299
497
|
* The state is a map `item key → fields`; key order is display order.
|
|
300
|
-
* Add, delete and move are component actions, mounted with `schemaComponent`.
|
|
498
|
+
* Add, delete, clone and move are component actions, mounted with `schemaComponent`.
|
|
301
499
|
*/
|
|
302
500
|
export declare class Repeater extends Field {
|
|
303
501
|
private _schema;
|
|
304
502
|
private _columns;
|
|
305
503
|
private _defaultItems;
|
|
306
504
|
private _maxItems;
|
|
505
|
+
private _minItems;
|
|
307
506
|
private _itemLinks;
|
|
507
|
+
private _simple;
|
|
508
|
+
private _grid;
|
|
509
|
+
private _collapsible;
|
|
510
|
+
private _collapsed;
|
|
511
|
+
private _persistCollapsed;
|
|
512
|
+
private _cloneable;
|
|
513
|
+
private _addable;
|
|
514
|
+
private _deletable;
|
|
515
|
+
private _reorderableWithButtons;
|
|
516
|
+
private _itemLabel;
|
|
517
|
+
private _itemNumbers;
|
|
518
|
+
private _truncateItemLabel;
|
|
519
|
+
private _headingTag;
|
|
520
|
+
private _addActionLabel;
|
|
521
|
+
private _addActionAlignment;
|
|
522
|
+
private _labelBetweenItems;
|
|
523
|
+
private _itemHeaders;
|
|
524
|
+
private _relationship;
|
|
308
525
|
static make(name: string): Repeater;
|
|
309
|
-
/** Item
|
|
310
|
-
schema(factory: () =>
|
|
526
|
+
/** Item components: a function called for each item. */
|
|
527
|
+
schema(factory: (() => Component[]) | Component[]): this;
|
|
311
528
|
/** Table display, one column per field. */
|
|
312
529
|
table(columns: TableColumn[]): this;
|
|
530
|
+
isTable(): boolean;
|
|
531
|
+
/**
|
|
532
|
+
* One field per item, without a card: the state is saved as a list of values (`['a@example.com', 'b@example.com']`).
|
|
533
|
+
* The field is cloned for each item.
|
|
534
|
+
*/
|
|
535
|
+
simple(field: Field | null): this;
|
|
313
536
|
defaultItems(count: number): this;
|
|
314
537
|
maxItems(count: number): this;
|
|
538
|
+
/** Minimum number of items, checked on the server. */
|
|
539
|
+
minItems(count: number | null): this;
|
|
315
540
|
private _reorderable;
|
|
316
541
|
/** `false`: items keep their order (e.g. a relationship without an order column). */
|
|
317
542
|
reorderable(condition?: boolean): this;
|
|
543
|
+
private _dragAndDrop;
|
|
544
|
+
/** Move up / move down buttons in each item header, besides drag and drop. */
|
|
545
|
+
reorderableWithButtons(condition?: boolean): this;
|
|
546
|
+
/** `false`: no drag and drop (buttons may still reorder, with `reorderableWithButtons()`). */
|
|
547
|
+
reorderableWithDragAndDrop(condition?: boolean): this;
|
|
548
|
+
/** Reordering is off with `reorderable(false)`, and for a relationship without `orderColumn()` (the order could not be saved). */
|
|
549
|
+
private isReorderable;
|
|
550
|
+
private canDrag;
|
|
551
|
+
private canMove;
|
|
318
552
|
/** Link shown on each row (an item action pointing to a URL). */
|
|
319
553
|
extraItemLink(resolver: (ctx: {
|
|
320
554
|
item: Record<string, unknown>;
|
|
321
555
|
key: string;
|
|
322
556
|
}) => ItemLink | null): this;
|
|
557
|
+
/** Items laid out in a grid (`2`, or `{ md: 2, xl: 3 }`). */
|
|
558
|
+
grid(columns?: Record<string, number> | number | null): this;
|
|
559
|
+
/** Items can be collapsed from their header; `collapsed()` collapses them on load. */
|
|
560
|
+
collapsible(condition?: boolean): this;
|
|
561
|
+
collapsed(condition?: boolean): this;
|
|
562
|
+
/** Keeps each item's collapsed state in the browser (local storage). */
|
|
563
|
+
persistCollapsed(condition?: boolean): this;
|
|
564
|
+
cloneable(condition?: boolean): this;
|
|
565
|
+
/** `false`: no "Add" button (and adding is refused on the server). */
|
|
566
|
+
addable(condition?: boolean): this;
|
|
567
|
+
/** `false`: no delete button (and deleting is refused on the server). */
|
|
568
|
+
deletable(condition?: boolean): this;
|
|
569
|
+
/** Item header label: a string, or a function of the item's state (`({ state }) => state.name ?? null`). Escaped. */
|
|
570
|
+
itemLabel(label: ((ctx: {
|
|
571
|
+
state: Record<string, unknown>;
|
|
572
|
+
key: string;
|
|
573
|
+
index: number;
|
|
574
|
+
}) => string | null) | string | null): this;
|
|
575
|
+
/** Item number after the label. */
|
|
576
|
+
itemNumbers(condition?: boolean): this;
|
|
577
|
+
truncateItemLabel(condition?: boolean): this;
|
|
578
|
+
/** `false`: items have no header (and so no buttons): only their fields. */
|
|
579
|
+
itemHeaders(condition?: boolean): this;
|
|
580
|
+
addActionLabel(label: string | null): this;
|
|
581
|
+
addActionAlignment(alignment: 'start' | 'center' | 'end' | null): this;
|
|
582
|
+
labelBetweenItems(label: string | null): this;
|
|
583
|
+
/**
|
|
584
|
+
* Items are the records of a has-many relationship of the form's model (Objection `relationMappings`): loaded when the form is
|
|
585
|
+
* filled, then created, updated and deleted once the record is saved. `orderColumn()` saves the items' order.
|
|
586
|
+
*/
|
|
587
|
+
relationship(name?: string | null, modifyQueryUsing?: ((query: any) => unknown) | null, options?: {
|
|
588
|
+
model?: any;
|
|
589
|
+
}): this;
|
|
590
|
+
orderColumn(column?: string | null): this;
|
|
591
|
+
private _orderColumnPending;
|
|
592
|
+
private itemComponents;
|
|
593
|
+
private itemFields;
|
|
323
594
|
/** Well-formed items only: keys come from the browser, so only simple keys are kept. */
|
|
324
595
|
getItems(): Record<string, Record<string, unknown>>;
|
|
325
596
|
private setItems;
|
|
326
597
|
private itemDefaults;
|
|
327
598
|
getDefaultState(): unknown;
|
|
328
|
-
/**
|
|
599
|
+
/** A list (records → `record-<id>` items; simple values → one-field items) or a keyed map, limited to the declared fields. */
|
|
329
600
|
hydrateState(value: unknown): unknown;
|
|
330
601
|
dehydrateState(): unknown;
|
|
602
|
+
/** Simple repeater: saved as a list of values. */
|
|
603
|
+
finalizeDehydratedState(state: unknown): unknown;
|
|
331
604
|
getChildSchemas(): Schema[];
|
|
605
|
+
private _childColumns;
|
|
606
|
+
/** Grid columns inside each item. */
|
|
607
|
+
columns(columns: Record<string, number> | number | null): this;
|
|
332
608
|
getValidationRules(): Promise<Rule[]>;
|
|
609
|
+
private relationInfo;
|
|
610
|
+
savesRelationships(): Promise<boolean>;
|
|
611
|
+
private relatedQuery;
|
|
612
|
+
loadStateFromRelationships(record: any): Promise<{
|
|
613
|
+
state: unknown;
|
|
614
|
+
} | null>;
|
|
615
|
+
/** Creates, updates and deletes the related records; only records of this owner (and query) are touched. */
|
|
616
|
+
saveRelationships(record: any): Promise<void>;
|
|
333
617
|
getActions(): Action[];
|
|
618
|
+
private itemLabelOf;
|
|
334
619
|
toHtml(): Promise<string>;
|
|
620
|
+
private toTableHtml;
|
|
335
621
|
}
|
|
336
|
-
/**
|
|
337
|
-
export declare
|
|
338
|
-
|
|
339
|
-
|
|
622
|
+
/** PHP date format (`M j, Y H:i`) to day.js (`MMM D, YYYY HH:mm`), as Filament's `convert_date_format()`. Escaped characters (`\at`) become literals. */
|
|
623
|
+
export declare function phpDateFormatToDayjs(format: string): string;
|
|
624
|
+
type DateLimit = Lazy<string | null, ComponentContext>;
|
|
625
|
+
/**
|
|
626
|
+
* Base of the date, time and date-time pickers: native browser input by default, or Filament's JavaScript picker with
|
|
627
|
+
* `native(false)` (display format, disabled dates, first day of the week, locale). Limits and disabled dates are checked on the server.
|
|
628
|
+
*/
|
|
629
|
+
declare abstract class TemporalField extends Field {
|
|
630
|
+
protected abstract hasDate(): boolean;
|
|
631
|
+
protected abstract hasTime(): boolean;
|
|
632
|
+
protected _seconds: boolean;
|
|
633
|
+
protected _native: boolean;
|
|
634
|
+
protected _maxDate: DateLimit;
|
|
635
|
+
protected _minDate: DateLimit;
|
|
636
|
+
protected _displayFormat: string | null;
|
|
637
|
+
protected _format: string | null;
|
|
638
|
+
protected _firstDayOfWeek: number;
|
|
639
|
+
protected _disabledDates: Lazy<string[], ComponentContext>;
|
|
640
|
+
protected _closeOnDateSelection: boolean;
|
|
641
|
+
protected _locale: string | null;
|
|
642
|
+
protected _timezone: string | null;
|
|
643
|
+
protected _hoursStep: number;
|
|
644
|
+
protected _minutesStep: number;
|
|
645
|
+
protected _secondsStep: number;
|
|
646
|
+
protected _defaultFocusedDate: string | null;
|
|
647
|
+
protected _temporalPlaceholder: string | null;
|
|
340
648
|
seconds(condition?: boolean): this;
|
|
649
|
+
hasSeconds(): boolean;
|
|
650
|
+
/** `false`: Filament's JavaScript picker instead of the browser's native input. */
|
|
651
|
+
native(condition?: boolean): this;
|
|
652
|
+
isNative(): boolean;
|
|
653
|
+
/** Display format of the JavaScript picker, in PHP's notation (`'d/m/Y'`, `'M j, Y H:i'`). */
|
|
654
|
+
displayFormat(format: string | null): this;
|
|
655
|
+
/** Format of the saved value, in PHP's notation (`'Y-m-d'` by default for dates, `'Y-m-d H:i:s'` with a time). */
|
|
656
|
+
format(format: string | null): this;
|
|
657
|
+
/** First day of the week in the JavaScript picker: 0 (Sunday) to 6. */
|
|
658
|
+
firstDayOfWeek(day: number): this;
|
|
659
|
+
weekStartsOnMonday(): this;
|
|
660
|
+
weekStartsOnSunday(): this;
|
|
661
|
+
/** Dates that cannot be picked (`YYYY-MM-DD`), also rejected on the server. */
|
|
662
|
+
disabledDates(dates: Lazy<string[], ComponentContext>): this;
|
|
663
|
+
closeOnDateSelection(condition?: boolean): this;
|
|
664
|
+
/** Locale of the JavaScript picker's month and day names (`'fr'`). */
|
|
665
|
+
locale(locale: string | null): this;
|
|
666
|
+
/** Shows and edits the value in this time zone, while it is saved in UTC (date-time pickers). */
|
|
667
|
+
timezone(timezone: string | null): this;
|
|
668
|
+
hoursStep(step: number): this;
|
|
669
|
+
minutesStep(step: number): this;
|
|
670
|
+
secondsStep(step: number): this;
|
|
671
|
+
/** Date focused when the JavaScript picker opens on an empty field. */
|
|
672
|
+
defaultFocusedDate(date: string | null): this;
|
|
673
|
+
placeholder(text: string | null): this;
|
|
674
|
+
private static resolveLimit;
|
|
675
|
+
protected limit(date: DateLimit): Promise<string | null>;
|
|
676
|
+
/** Latest accepted date: `'today'`, a date, or a context function (`({ get }) => get('ends_at')`). */
|
|
677
|
+
maxDate(date: DateLimit): this;
|
|
678
|
+
minDate(date: DateLimit): this;
|
|
679
|
+
/** Comparable string of a value: the date only for date pickers, the time only for time pickers. */
|
|
680
|
+
private comparable;
|
|
681
|
+
getValidationRules(): Promise<Rule[]>;
|
|
682
|
+
/** Record value to form state, shown in the field's time zone. */
|
|
341
683
|
hydrateState(value: unknown): unknown;
|
|
684
|
+
/** Form state as the input expects it. */
|
|
685
|
+
protected stateOf(local: string): string;
|
|
686
|
+
/** Wall-clock value of the field's time zone to UTC. */
|
|
687
|
+
private toUtc;
|
|
688
|
+
/** Saved value: in UTC, in `format()` (or the default format). */
|
|
689
|
+
dehydrateState(state: unknown): unknown;
|
|
690
|
+
protected defaultDisplayFormat(): string;
|
|
691
|
+
protected nativeType(): string;
|
|
342
692
|
toHtml(): Promise<string>;
|
|
343
693
|
}
|
|
344
|
-
/**
|
|
345
|
-
export declare class
|
|
346
|
-
|
|
694
|
+
/** Date picker: native `<input type="date">` by default; the saved state is `YYYY-MM-DD`. */
|
|
695
|
+
export declare class DatePicker extends TemporalField {
|
|
696
|
+
static make(name: string): DatePicker;
|
|
697
|
+
protected hasDate(): boolean;
|
|
698
|
+
protected hasTime(): boolean;
|
|
699
|
+
}
|
|
700
|
+
/** Time picker: native `<input type="time">` by default; the state is `HH:MM:SS` (`HH:MM` with `seconds(false)`). */
|
|
701
|
+
export declare class TimePicker extends TemporalField {
|
|
702
|
+
static make(name: string): TimePicker;
|
|
703
|
+
protected hasDate(): boolean;
|
|
704
|
+
protected hasTime(): boolean;
|
|
705
|
+
}
|
|
706
|
+
/** Date-time picker: native `datetime-local` input by default; the saved state is `YYYY-MM-DD HH:MM:SS`. */
|
|
707
|
+
export declare class DateTimePicker extends TemporalField {
|
|
347
708
|
static make(name: string): DateTimePicker;
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
toHtml(): Promise<string>;
|
|
709
|
+
protected hasDate(): boolean;
|
|
710
|
+
protected hasTime(): boolean;
|
|
351
711
|
}
|
|
352
712
|
/** Single choice as radio buttons. */
|
|
353
713
|
export declare class Radio extends Field {
|
|
@@ -362,6 +722,12 @@ export declare class Radio extends Field {
|
|
|
362
722
|
/** Options side by side. */
|
|
363
723
|
inline(condition?: boolean): this;
|
|
364
724
|
live(condition?: boolean): this;
|
|
725
|
+
private _disableOptionWhen;
|
|
726
|
+
/** Options that cannot be picked; they are refused on the server too. */
|
|
727
|
+
disableOptionWhen(condition: ((value: string, label: string) => boolean) | null): this;
|
|
728
|
+
isOptionDisabled(value: string, label: string): boolean;
|
|
729
|
+
/** "Yes" (`1`) and "No" (`0`) options. */
|
|
730
|
+
boolean(trueLabel?: string | null, falseLabel?: string | null): this;
|
|
365
731
|
getValidationRules(): Promise<Rule[]>;
|
|
366
732
|
toHtml(): Promise<string>;
|
|
367
733
|
}
|
|
@@ -371,6 +737,27 @@ export declare class Textarea extends Field {
|
|
|
371
737
|
static make(name: string): Textarea;
|
|
372
738
|
rows(rows: number): this;
|
|
373
739
|
maxLength(length: number): this;
|
|
740
|
+
private _minLength;
|
|
741
|
+
private _placeholder;
|
|
742
|
+
private _readOnly;
|
|
743
|
+
private _autosize;
|
|
744
|
+
private _grammarly;
|
|
745
|
+
private _trim;
|
|
746
|
+
minLength(length: number): this;
|
|
747
|
+
/** Exact length. */
|
|
748
|
+
length(length: number): this;
|
|
749
|
+
placeholder(text: string | null): this;
|
|
750
|
+
readOnly(condition?: boolean): this;
|
|
751
|
+
/** The textarea grows with its content. */
|
|
752
|
+
autosize(condition?: boolean): this;
|
|
753
|
+
/** Stops the Grammarly extension from analyzing the content. */
|
|
754
|
+
disableGrammarly(condition?: boolean): this;
|
|
755
|
+
/** Removes the spaces around the value before it is validated and saved. */
|
|
756
|
+
trim(condition?: boolean): this;
|
|
757
|
+
hydrateState(value: unknown): unknown;
|
|
758
|
+
/** `trim()`: the submitted value is trimmed before it is validated and saved. */
|
|
759
|
+
protected stateForValidation(state: unknown): unknown;
|
|
760
|
+
dehydrateState(state: unknown): unknown;
|
|
374
761
|
toHtml(): Promise<string>;
|
|
375
762
|
}
|
|
376
763
|
/** Tag list input: the state is an array of strings. */
|
|
@@ -384,10 +771,28 @@ export declare class TagsInput extends Field {
|
|
|
384
771
|
suggestions(suggestions: string[]): this;
|
|
385
772
|
/** Keys that confirm the current tag, besides Enter (`['Tab', ',']`). */
|
|
386
773
|
splitKeys(keys: string[]): this;
|
|
774
|
+
private _separator;
|
|
775
|
+
private _tagPrefix;
|
|
776
|
+
private _tagSuffix;
|
|
777
|
+
private _reorderable;
|
|
778
|
+
private _tagColor;
|
|
779
|
+
private _tagRules;
|
|
780
|
+
/** Saves the tags as one string joined with this separator (`'a,b,c'`) instead of a list. */
|
|
781
|
+
separator(separator?: string | null): this;
|
|
782
|
+
/** Text shown before / after each tag (not saved). */
|
|
783
|
+
tagPrefix(prefix: string | null): this;
|
|
784
|
+
tagSuffix(suffix: string | null): this;
|
|
785
|
+
/** Tags can be reordered by dragging. */
|
|
786
|
+
reorderable(condition?: boolean): this;
|
|
787
|
+
/** Badge color of the tags (`primary` by default). */
|
|
788
|
+
color(color: string | null): this;
|
|
789
|
+
/** Rules applied to each tag (e.g. a maximum length); the message names the tag. */
|
|
790
|
+
nestedRecursiveRules(rules: (Rule | string)[]): this;
|
|
387
791
|
getDefaultState(): unknown;
|
|
388
792
|
hydrateState(value: unknown): unknown;
|
|
389
|
-
/** Only non-empty strings are saved, whatever shape the browser sends. */
|
|
793
|
+
/** Only non-empty strings are saved, whatever shape the browser sends (joined with the separator, if any). */
|
|
390
794
|
dehydrateState(state: unknown): unknown;
|
|
795
|
+
getValidationRules(): Promise<Rule[]>;
|
|
391
796
|
toHtml(): Promise<string>;
|
|
392
797
|
}
|
|
393
798
|
/** On/off switch. */
|
|
@@ -395,6 +800,19 @@ export declare class Toggle extends Field {
|
|
|
395
800
|
static make(name: string): Toggle;
|
|
396
801
|
getDefaultState(): unknown;
|
|
397
802
|
hydrateState(value: unknown): unknown;
|
|
803
|
+
private _onIcon;
|
|
804
|
+
private _offIcon;
|
|
805
|
+
private _onColor;
|
|
806
|
+
private _offColor;
|
|
807
|
+
private _inline;
|
|
808
|
+
/** Icons inside the switch's knob. */
|
|
809
|
+
onIcon(icon: string | null): this;
|
|
810
|
+
offIcon(icon: string | null): this;
|
|
811
|
+
/** Colors when on (`primary` by default) and off (`gray`). */
|
|
812
|
+
onColor(color: string | null): this;
|
|
813
|
+
offColor(color: string | null): this;
|
|
814
|
+
/** `false`: the label goes above the switch instead of beside it. */
|
|
815
|
+
inline(condition?: boolean): this;
|
|
398
816
|
toHtml(): Promise<string>;
|
|
399
817
|
}
|
|
400
818
|
/** Single choice shown as buttons. */
|
|
@@ -417,6 +835,34 @@ export declare class ToggleButtons extends Field {
|
|
|
417
835
|
inline(condition?: boolean): this;
|
|
418
836
|
/** Buttons joined into a single group. */
|
|
419
837
|
grouped(condition?: boolean): this;
|
|
838
|
+
private _multiple;
|
|
839
|
+
private _tooltips;
|
|
840
|
+
private _size;
|
|
841
|
+
private _labelsHidden;
|
|
842
|
+
private _fullWidth;
|
|
843
|
+
private _columns;
|
|
844
|
+
private _disableOptionWhen;
|
|
845
|
+
/** Several buttons can be selected: the state is a list of values. */
|
|
846
|
+
multiple(condition?: boolean): this;
|
|
847
|
+
/** Tooltip per value. */
|
|
848
|
+
tooltips(tooltips: Record<string, string>): this;
|
|
849
|
+
/** Button size: `xs`, `sm`, `md` (default), `lg` or `xl`. */
|
|
850
|
+
size(size: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | null): this;
|
|
851
|
+
/** Icons only: the labels stay for screen readers. */
|
|
852
|
+
hiddenButtonLabels(condition?: boolean): this;
|
|
853
|
+
/** Buttons stretch to the width of the field. */
|
|
854
|
+
fullWidth(condition?: boolean): this;
|
|
855
|
+
/** Number of columns the buttons are spread over (from `lg`), when not inline. */
|
|
856
|
+
columns(columns: number | null): this;
|
|
857
|
+
/** Options that cannot be selected; they are refused on the server too. */
|
|
858
|
+
disableOptionWhen(condition: ((value: string, label: string) => boolean) | null): this;
|
|
859
|
+
isOptionDisabled(value: string, label: string): boolean;
|
|
860
|
+
/** "Yes" (`1`) and "No" (`0`) buttons, green and red, with check and cross icons. */
|
|
861
|
+
boolean(trueLabel?: string | null, falseLabel?: string | null): this;
|
|
862
|
+
getDefaultState(): unknown;
|
|
863
|
+
hydrateState(value: unknown): unknown;
|
|
864
|
+
/** Multiple: only offered values, in option order. */
|
|
865
|
+
dehydrateState(state: unknown): unknown;
|
|
420
866
|
getValidationRules(): Promise<Rule[]>;
|
|
421
867
|
toHtml(): Promise<string>;
|
|
422
868
|
}
|
|
@@ -431,22 +877,50 @@ export declare function richHtmlToDocument(html: string | null | undefined): Ric
|
|
|
431
877
|
* so it is rendered then re-parsed to keep only what the schema accepts.
|
|
432
878
|
*/
|
|
433
879
|
export declare function richDocumentToHtml(document: unknown): string | null;
|
|
434
|
-
/**
|
|
435
|
-
|
|
436
|
-
* Not supported yet: attachments, custom blocks, mentions.
|
|
437
|
-
*/
|
|
880
|
+
/** Tools of the rich editor's toolbar, in their default groups. */
|
|
881
|
+
export declare const RICH_EDITOR_TOOLS: string[][];
|
|
438
882
|
export declare class RichEditor extends Field {
|
|
883
|
+
private _toolbar;
|
|
884
|
+
private _disabledTools;
|
|
885
|
+
private _json;
|
|
886
|
+
private _richPlaceholder;
|
|
887
|
+
private _attachmentsStorage;
|
|
888
|
+
private _attachmentsDirectory;
|
|
889
|
+
private _attachmentTypes;
|
|
890
|
+
private _attachmentMaxSize;
|
|
439
891
|
static make(name: string): RichEditor;
|
|
892
|
+
/** Toolbar tools, by group (`[['bold', 'italic', 'link'], ['h2', 'h3'], ['undo', 'redo']]`); see `RICH_EDITOR_TOOLS`. */
|
|
893
|
+
toolbarButtons(groups: string[][] | string[]): this;
|
|
894
|
+
/** Removes buttons; with no argument, removes them all. */
|
|
895
|
+
disableToolbarButtons(tools?: string[]): this;
|
|
896
|
+
disableAllToolbarButtons(condition?: boolean): this;
|
|
897
|
+
/** Saves the content as the editor's JSON document instead of HTML. */
|
|
898
|
+
json(condition?: boolean): this;
|
|
899
|
+
placeholder(text: string | null): this;
|
|
900
|
+
/** Where files attached in the editor are stored (`FileUpload.storage` by default); without storage, attaching is off. */
|
|
901
|
+
fileAttachmentsStorage(storage: FileStorage | null): this;
|
|
902
|
+
fileAttachmentsDirectory(directory: string | null): this;
|
|
903
|
+
/** Accepted types of attached files, checked on the file's content (images only: they are inserted as images). */
|
|
904
|
+
fileAttachmentsAcceptedFileTypes(types: string[]): this;
|
|
905
|
+
/** Maximum size of attached files, in kilobytes. */
|
|
906
|
+
fileAttachmentsMaxSize(kilobytes: number): this;
|
|
907
|
+
private attachmentsStorage;
|
|
908
|
+
private tools;
|
|
440
909
|
hydrateState(value: unknown): unknown;
|
|
441
910
|
getDefaultState(): unknown;
|
|
911
|
+
/** HTML (sanitized by the editor's schema), or the JSON document with `json()` (normalized through the same schema). */
|
|
442
912
|
dehydrateState(state: unknown): unknown;
|
|
443
913
|
getValidationRules(): Promise<Rule[]>;
|
|
444
914
|
getExposedMethods(): string[];
|
|
445
915
|
getMentionSearchResultsForJs(): unknown[];
|
|
446
916
|
getMentionLabelsForJs(): unknown[];
|
|
447
917
|
getCustomBlockPreviewsForJs(): unknown[];
|
|
448
|
-
|
|
449
|
-
|
|
918
|
+
/**
|
|
919
|
+
* URL of a file the editor just uploaded: the file is checked (type from its content, size), stored, and its public URL returned.
|
|
920
|
+
* It stays stored even if the form is not saved.
|
|
921
|
+
*/
|
|
922
|
+
getUploadedFileAttachmentTemporaryUrl(args?: unknown): Promise<string | null>;
|
|
923
|
+
saveUploadedFileAttachmentAndGetUrl(args?: unknown): Promise<string | null>;
|
|
450
924
|
/** Toolbar "link" action: a modal (URL, new tab), then commands sent back to the browser editor. */
|
|
451
925
|
getActions(): Action[];
|
|
452
926
|
toHtml(): Promise<string>;
|
|
@@ -454,14 +928,22 @@ export declare class RichEditor extends Field {
|
|
|
454
928
|
/** Color picker (hex format). */
|
|
455
929
|
export declare class ColorPicker extends Field {
|
|
456
930
|
static make(name: string): ColorPicker;
|
|
457
|
-
|
|
931
|
+
private _format;
|
|
932
|
+
/** Color format of the state: `#ff0000` (default), `rgb(255, 0, 0)`, `rgba(255, 0, 0, 1)` or `hsl(0, 100%, 50%)`. */
|
|
933
|
+
format(format: 'hex' | 'rgb' | 'rgba' | 'hsl'): this;
|
|
458
934
|
hex(): this;
|
|
459
|
-
|
|
935
|
+
rgb(): this;
|
|
936
|
+
rgba(): this;
|
|
937
|
+
hsl(): this;
|
|
938
|
+
getValidationRules(): Promise<Rule[]>;
|
|
460
939
|
toHtml(): Promise<string>;
|
|
461
940
|
}
|
|
462
941
|
export declare class Checkbox extends Field {
|
|
942
|
+
private _inline;
|
|
463
943
|
static make(name: string): Checkbox;
|
|
464
944
|
getDefaultState(): unknown;
|
|
945
|
+
/** `false`: the label goes above the checkbox instead of beside it. */
|
|
946
|
+
inline(condition?: boolean): this;
|
|
465
947
|
toHtml(): Promise<string>;
|
|
466
948
|
}
|
|
467
949
|
/** Checkboxes for a list of values (no search or "select all" yet). */
|
|
@@ -472,6 +954,23 @@ export declare class CheckboxList extends Field {
|
|
|
472
954
|
options(options: Options): this;
|
|
473
955
|
/** Number of columns the options are spread over (from `lg`). */
|
|
474
956
|
columns(columns: number | null): this;
|
|
957
|
+
private _descriptions;
|
|
958
|
+
private _searchable;
|
|
959
|
+
private _bulkToggleable;
|
|
960
|
+
private _disableOptionWhen;
|
|
961
|
+
/** Helper text per value, under the option label. */
|
|
962
|
+
descriptions(descriptions: Record<string, string>): this;
|
|
963
|
+
/** A search field filters the options in the browser. */
|
|
964
|
+
searchable(condition?: boolean): this;
|
|
965
|
+
private _searchPrompt;
|
|
966
|
+
private _noSearchResultsMessage;
|
|
967
|
+
searchPrompt(prompt: string): this;
|
|
968
|
+
noSearchResultsMessage(message: string): this;
|
|
969
|
+
/** "Select all" / "Deselect all" links. */
|
|
970
|
+
bulkToggleable(condition?: boolean): this;
|
|
971
|
+
/** Options that cannot be checked; they are refused on the server too. */
|
|
972
|
+
disableOptionWhen(condition: ((value: string, label: string) => boolean) | null): this;
|
|
973
|
+
isOptionDisabled(value: string, label: string): boolean;
|
|
475
974
|
getDefaultState(): unknown;
|
|
476
975
|
hydrateState(value: unknown): unknown;
|
|
477
976
|
/** Only offered values are kept, without duplicates, in option order. */
|
|
@@ -488,8 +987,29 @@ export declare class KeyValue extends Field {
|
|
|
488
987
|
keyLabel(label: string): this;
|
|
489
988
|
valueLabel(label: string): this;
|
|
490
989
|
reorderable(condition?: boolean): this;
|
|
990
|
+
private _addable;
|
|
991
|
+
private _deletable;
|
|
992
|
+
private _editableKeys;
|
|
993
|
+
private _editableValues;
|
|
994
|
+
private _keyPlaceholder;
|
|
995
|
+
private _valuePlaceholder;
|
|
996
|
+
private _addLabel;
|
|
997
|
+
private _deleteLabel;
|
|
998
|
+
/** `false`: no "Add row" button. */
|
|
999
|
+
addable(condition?: boolean): this;
|
|
1000
|
+
/** `false`: rows cannot be deleted. */
|
|
1001
|
+
deletable(condition?: boolean): this;
|
|
1002
|
+
/** `false`: keys cannot be changed. The server keeps the saved keys. */
|
|
1003
|
+
editableKeys(condition?: boolean): this;
|
|
1004
|
+
/** `false`: values cannot be changed. */
|
|
1005
|
+
editableValues(condition?: boolean): this;
|
|
1006
|
+
keyPlaceholder(text: string | null): this;
|
|
1007
|
+
valuePlaceholder(text: string | null): this;
|
|
1008
|
+
addActionLabel(label: string | null): this;
|
|
1009
|
+
deleteActionLabel(label: string | null): this;
|
|
491
1010
|
getDefaultState(): unknown;
|
|
492
1011
|
private static toPairs;
|
|
1012
|
+
private _originalValue;
|
|
493
1013
|
hydrateState(value: unknown): unknown;
|
|
494
1014
|
/** Flat object of strings: empty keys, nested objects and dangerous keys are dropped; 200 pairs at most. */
|
|
495
1015
|
dehydrateState(state: unknown): unknown;
|
|
@@ -504,7 +1024,7 @@ export declare class RawJs {
|
|
|
504
1024
|
}
|
|
505
1025
|
/**
|
|
506
1026
|
* Markdown editor (EasyMDE). The state is raw Markdown text, to sanitize before any HTML display.
|
|
507
|
-
*
|
|
1027
|
+
* Files can be attached (images, stored on upload) when a storage is set (`fileAttachmentsStorage()` or `FileUpload.storage`); when read-only (`disabled()`),
|
|
508
1028
|
* the text is shown escaped, without Markdown conversion.
|
|
509
1029
|
*/
|
|
510
1030
|
export declare class MarkdownEditor extends Field {
|
|
@@ -536,9 +1056,23 @@ export declare class MarkdownEditor extends Field {
|
|
|
536
1056
|
minLength(length: number): this;
|
|
537
1057
|
hydrateState(value: unknown): unknown;
|
|
538
1058
|
getValidationRules(): Promise<Rule[]>;
|
|
1059
|
+
private _attachmentsStorage;
|
|
1060
|
+
private _attachmentsDirectory;
|
|
1061
|
+
private _attachmentTypes;
|
|
1062
|
+
private _attachmentMaxSize;
|
|
1063
|
+
/** Where attached files are stored (`FileUpload.storage` by default); without storage, the "Attach files" button is hidden. */
|
|
1064
|
+
fileAttachmentsStorage(storage: FileStorage | null): this;
|
|
1065
|
+
fileAttachmentsDirectory(directory: string | null): this;
|
|
1066
|
+
/** Accepted types of attached files (images), checked on the file's content. */
|
|
1067
|
+
fileAttachmentsAcceptedFileTypes(types: string[]): this;
|
|
1068
|
+
/** Maximum size of attached files, in kilobytes. */
|
|
1069
|
+
fileAttachmentsMaxSize(kilobytes: number): this;
|
|
1070
|
+
private canAttachFiles;
|
|
1071
|
+
private visibleToolbar;
|
|
539
1072
|
getExposedMethods(): string[];
|
|
540
1073
|
getUploadedFileAttachmentTemporaryUrl(): null;
|
|
541
|
-
|
|
1074
|
+
/** Stores the file just uploaded to `componentFileAttachments.<state path>` and returns its URL. */
|
|
1075
|
+
saveUploadedFileAttachmentAndGetUrl(): Promise<string | null>;
|
|
542
1076
|
toHtml(): Promise<string>;
|
|
543
1077
|
}
|
|
544
1078
|
/** Code editor (CodeMirror): highlighting from `language()`, line wrapping with `wrap()`. */
|
|
@@ -681,6 +1215,10 @@ export declare class Placeholder extends Component {
|
|
|
681
1215
|
export declare function fillSchema(schema: Schema, target: Record<string, unknown>): void;
|
|
682
1216
|
/** Fills the form state from a record, field by field. */
|
|
683
1217
|
export declare function fillSchemaFromRecord(schema: Schema, target: Record<string, unknown>, record: Record<string, unknown>): void;
|
|
1218
|
+
/** Fills the fields that load their state from the record's relationships (`loadStateFromRelationshipsUsing()`, `Select::relationship()`…). */
|
|
1219
|
+
export declare function loadSchemaRelationships(schema: Schema, target: Record<string, unknown>, record: unknown): Promise<void>;
|
|
1220
|
+
/** Saves the visible fields that write the record's relationships, once the record is created or updated. */
|
|
1221
|
+
export declare function saveSchemaRelationships(schema: Schema, record: unknown): Promise<void>;
|
|
684
1222
|
/** Validates every visible field of a schema; returns errors by state path. */
|
|
685
1223
|
export declare function validateSchema(schema: Schema): Promise<Record<string, string[]>>;
|
|
686
1224
|
/** State to save: only declared, visible, dehydrated fields; an empty string becomes `null`. */
|
|
@@ -795,17 +1333,39 @@ export type FileUploadEntry = {
|
|
|
795
1333
|
};
|
|
796
1334
|
/** Where files go once the form is saved. */
|
|
797
1335
|
export interface FileStorage {
|
|
798
|
-
/** Stores a temporary file and returns its key (relative path). */
|
|
799
|
-
store(file: TemporaryUpload, directory: string | null): Promise<string>;
|
|
1336
|
+
/** Stores a temporary file and returns its key (relative path); `name` is the file name to use instead of a random one. */
|
|
1337
|
+
store(file: TemporaryUpload, directory: string | null, name?: string | null): Promise<string>;
|
|
800
1338
|
info(key: string): Promise<UploadedFileInfo | null>;
|
|
801
1339
|
}
|
|
802
1340
|
/** Local disk storage, served under a public URL. File names are random; the extension comes from the detected type. */
|
|
1341
|
+
/**
|
|
1342
|
+
* A file name chosen by the application or the user, made safe for storage: no directory part, only letters, digits, `_` and
|
|
1343
|
+
* `-`, and always the extension detected from the file's content (an uploaded `shell.php` declared as an image is stored
|
|
1344
|
+
* as `shell.png`).
|
|
1345
|
+
*/
|
|
1346
|
+
export declare function safeStorageName(name: string, extension: string): string;
|
|
1347
|
+
/** Width and height of a PNG, GIF, JPEG or WebP image, read from its header; `null` for other files. */
|
|
1348
|
+
export declare function readImageSize(path: string): {
|
|
1349
|
+
width: number;
|
|
1350
|
+
height: number;
|
|
1351
|
+
} | null;
|
|
1352
|
+
export type ImageDimensions = {
|
|
1353
|
+
minWidth?: number;
|
|
1354
|
+
maxWidth?: number;
|
|
1355
|
+
minHeight?: number;
|
|
1356
|
+
maxHeight?: number;
|
|
1357
|
+
width?: number;
|
|
1358
|
+
height?: number;
|
|
1359
|
+
minRatio?: number;
|
|
1360
|
+
maxRatio?: number;
|
|
1361
|
+
ratio?: number;
|
|
1362
|
+
};
|
|
803
1363
|
export declare class LocalFileStorage implements FileStorage {
|
|
804
1364
|
private root;
|
|
805
1365
|
private baseUrl;
|
|
806
1366
|
constructor(root: string, baseUrl: string);
|
|
807
1367
|
private resolve;
|
|
808
|
-
store(file: TemporaryUpload, directory: string | null): Promise<string>;
|
|
1368
|
+
store(file: TemporaryUpload, directory: string | null, name?: string | null): Promise<string>;
|
|
809
1369
|
info(key: string): Promise<UploadedFileInfo | null>;
|
|
810
1370
|
}
|
|
811
1371
|
/**
|
|
@@ -825,7 +1385,98 @@ export declare class FileUpload extends Field {
|
|
|
825
1385
|
private _storeFiles;
|
|
826
1386
|
private _storage;
|
|
827
1387
|
private _getUploadedFileUsing;
|
|
1388
|
+
private _minSize;
|
|
1389
|
+
private _ui;
|
|
1390
|
+
private _avatar;
|
|
1391
|
+
private _imageEditor;
|
|
1392
|
+
private _circleCropper;
|
|
1393
|
+
private _editorAspectRatios;
|
|
1394
|
+
private _cropAspectRatio;
|
|
1395
|
+
private _imageAspectRatios;
|
|
1396
|
+
private _dimensions;
|
|
1397
|
+
private _deletable;
|
|
1398
|
+
private _preserveFilenames;
|
|
1399
|
+
private _fileNameUsing;
|
|
1400
|
+
private _fileNamesField;
|
|
1401
|
+
private _storedNames;
|
|
1402
|
+
private _alignment;
|
|
1403
|
+
private _placeholder;
|
|
828
1404
|
static make(name: string): FileUpload;
|
|
1405
|
+
/** Minimum file size, in kilobytes. */
|
|
1406
|
+
minSize(kilobytes: number | null): this;
|
|
1407
|
+
/** Download button on each saved file. */
|
|
1408
|
+
downloadable(condition?: boolean): this;
|
|
1409
|
+
/** Button opening each saved file in a new tab. */
|
|
1410
|
+
openable(condition?: boolean): this;
|
|
1411
|
+
/** `false`: no preview of images. */
|
|
1412
|
+
previewable(condition?: boolean): this;
|
|
1413
|
+
/** `false`: files cannot be pasted from the clipboard. */
|
|
1414
|
+
pasteable(condition?: boolean): this;
|
|
1415
|
+
/** New files are added after the existing ones (instead of before). */
|
|
1416
|
+
appendFiles(condition?: boolean): this;
|
|
1417
|
+
/** `false`: saved files cannot be removed (the remove button is hidden, and removing is refused on the server). */
|
|
1418
|
+
deletable(condition?: boolean): this;
|
|
1419
|
+
/** `'grid'` (with `multiple()`), `'compact'`, `'integrated'` or `'circle'`. */
|
|
1420
|
+
panelLayout(layout: 'grid' | 'compact' | 'integrated' | 'circle' | string | null): this;
|
|
1421
|
+
panelAspectRatio(ratio: string | null): this;
|
|
1422
|
+
itemPanelAspectRatio(ratio: string | null): this;
|
|
1423
|
+
imagePreviewHeight(height: string | null): this;
|
|
1424
|
+
loadingIndicatorPosition(position: string): this;
|
|
1425
|
+
removeUploadedFileButtonPosition(position: string): this;
|
|
1426
|
+
uploadButtonPosition(position: string): this;
|
|
1427
|
+
uploadProgressIndicatorPosition(position: string): this;
|
|
1428
|
+
/** Message shown while a file uploads. */
|
|
1429
|
+
uploadingMessage(message: string): this;
|
|
1430
|
+
/** Number of files uploaded at the same time. */
|
|
1431
|
+
maxParallelUploads(count: number | null): this;
|
|
1432
|
+
/** Extension → MIME type map for files the browser cannot type (`{ zip: 'application/zip' }`). */
|
|
1433
|
+
mimeTypeMap(map: Record<string, string>): this;
|
|
1434
|
+
/** `false`: images keep their EXIF orientation. */
|
|
1435
|
+
orientImagesFromExif(condition?: boolean): this;
|
|
1436
|
+
alignment(alignment: 'start' | 'center' | 'end' | null): this;
|
|
1437
|
+
/** Text of the drop area. */
|
|
1438
|
+
placeholder(text: string | null): this;
|
|
1439
|
+
/** Round avatar: one image, cropped to a square and shown as a circle. */
|
|
1440
|
+
avatar(): this;
|
|
1441
|
+
/** Image editor (crop, rotate, flip, zoom) opened from each image, powered by Cropper.js in the browser. */
|
|
1442
|
+
imageEditor(condition?: boolean): this;
|
|
1443
|
+
/** Aspect ratios offered by the image editor (`['16:9', '4:3', '1:1']`; `null` for a free crop). */
|
|
1444
|
+
imageEditorAspectRatioOptions(ratios: (string | null)[]): this;
|
|
1445
|
+
imageEditorAspectRatios(ratios: (string | null)[]): this;
|
|
1446
|
+
/** Cropper.js view mode (1, 2 or 3). */
|
|
1447
|
+
imageEditorMode(mode: 1 | 2 | 3): this;
|
|
1448
|
+
imageEditorEmptyFillColor(color: string | null): this;
|
|
1449
|
+
imageEditorViewportWidth(width: string | number | null): this;
|
|
1450
|
+
imageEditorViewportHeight(height: string | number | null): this;
|
|
1451
|
+
private _autoOpenEditor;
|
|
1452
|
+
/** With `imageEditor()` and a single aspect ratio, opens the editor when an uploaded image has another ratio (on by default). */
|
|
1453
|
+
automaticallyOpenImageEditorForAspectRatio(condition?: boolean): this;
|
|
1454
|
+
private autoOpenEditorRatio;
|
|
1455
|
+
/** Circle crop in the image editor (avatars). */
|
|
1456
|
+
circleCropper(condition?: boolean): this;
|
|
1457
|
+
/** Crops images to this ratio in the browser before upload (`'16:9'`), without opening the editor. */
|
|
1458
|
+
automaticallyCropImagesToAspectRatio(ratio: string | null): this;
|
|
1459
|
+
imageCropAspectRatio(ratio: string | null): this;
|
|
1460
|
+
/** Resizes images in the browser before upload (`'cover'`, `'contain'` or `'force'`). */
|
|
1461
|
+
automaticallyResizeImagesMode(mode: 'cover' | 'contain' | 'force' | null): this;
|
|
1462
|
+
automaticallyResizeImagesToWidth(width: string | number | null): this;
|
|
1463
|
+
automaticallyResizeImagesToHeight(height: string | number | null): this;
|
|
1464
|
+
automaticallyUpscaleImagesWhenResizing(condition?: boolean): this;
|
|
1465
|
+
imageResizeMode(mode: 'cover' | 'contain' | 'force' | null): this;
|
|
1466
|
+
imageResizeTargetWidth(width: string | number | null): this;
|
|
1467
|
+
imageResizeTargetHeight(height: string | number | null): this;
|
|
1468
|
+
/** Accepted aspect ratio(s) of uploaded images (`'16:9'` or a list), checked on the server. */
|
|
1469
|
+
imageAspectRatio(ratio: string | string[] | null): this;
|
|
1470
|
+
/** Width, height and ratio bounds of uploaded images (`{ minWidth: 800, maxHeight: 1080 }`), checked on the server. */
|
|
1471
|
+
imageDimensions(dimensions: ImageDimensions | null): this;
|
|
1472
|
+
/** Stores files under their original (sanitized) names. See the security notes in the docs. */
|
|
1473
|
+
preserveFilenames(condition?: boolean): this;
|
|
1474
|
+
/** Name of the stored file, from the temporary file; sanitized, and its extension is the detected one. */
|
|
1475
|
+
getUploadedFileNameForStorageUsing(callback: ((file: TemporaryUpload, ctx: ComponentContext) => string | Promise<string>) | null): this;
|
|
1476
|
+
/** Saves the original file names (keyed by stored file) in another attribute of the record. */
|
|
1477
|
+
storeFileNamesIn(field: string | null): this;
|
|
1478
|
+
/** Extra saved values, next to the field (the original file names of `storeFileNamesIn()`). */
|
|
1479
|
+
getExtraDehydratedState(): Record<string, unknown>;
|
|
829
1480
|
multiple(condition?: boolean): this;
|
|
830
1481
|
maxFiles(count: number | null): this;
|
|
831
1482
|
/** Maximum file size, in kilobytes. */
|
|
@@ -849,6 +1500,8 @@ export declare class FileUpload extends Field {
|
|
|
849
1500
|
/** Stored keys the current record already owns: the only ones accepted back from the browser. */
|
|
850
1501
|
private originalKeys;
|
|
851
1502
|
private isTemporary;
|
|
1503
|
+
/** Original names saved by `storeFileNamesIn()`, by stored key. */
|
|
1504
|
+
private savedFileNames;
|
|
852
1505
|
getExposedMethods(): string[];
|
|
853
1506
|
getUploadedFiles(): Promise<Record<string, UploadedFileInfo | null>>;
|
|
854
1507
|
private writeState;
|
|
@@ -861,6 +1514,7 @@ export declare class FileUpload extends Field {
|
|
|
861
1514
|
validate(): Promise<string[]>;
|
|
862
1515
|
/** On save: temporary files are stored, unrecognized existing keys are dropped. */
|
|
863
1516
|
dehydrateState(): Promise<unknown>;
|
|
1517
|
+
/** Filament's image editor dialog (Cropper.js), rendered once per field. */
|
|
1518
|
+
private imageEditorHtml;
|
|
864
1519
|
toHtml(): Promise<string>;
|
|
865
1520
|
}
|
|
866
|
-
export {};
|