@navette-js/schemas 1.0.0-beta.1 → 1.0.0-beta.2

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/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # @navette-js/schemas
2
2
 
3
- Layout components and schemas for Navette, the Node.js port of Filament.
3
+ Layout components and schemas for Navette admin panels.
4
4
 
5
- Part of [Navette](https://github.com/NavetteJS/navette), a Node.js port of [Filament](https://filamentphp.com). Install the whole framework with `npm install @navette-js/panels`.
5
+ Part of [Navette](https://github.com/NavetteJS/navette), admin panels for Node.js. Start a project with `npm create navette@latest`, or install the framework with `npm install @navette-js/panels`.
6
6
 
7
7
  **Beta:** the API may still change between beta releases.
8
8
 
package/lib/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { HtmlString, type ColorManager, type Lazy } from '@navette-js/support';
2
- /** Ce qu'un schéma attend du composant à état qui l'héberge. */
2
+ /** What a schema expects from the stateful component hosting it. */
3
3
  export interface SchemaHost {
4
4
  readonly id: string;
5
5
  _errors: Record<string, string[]>;
@@ -17,10 +17,10 @@ type SpanValue = number | string | ((ctx: ComponentContext) => number | string |
17
17
  type ColumnSpan = Record<string, SpanValue> | number | string;
18
18
  export declare abstract class Component {
19
19
  private _grow;
20
- /** Dans un Flex : `false` pour garder la largeur naturelle au lieu d'occuper la place disponible. */
20
+ /** Inside a Flex: `false` keeps the natural width instead of filling the available space. */
21
21
  grow(condition?: boolean): this;
22
22
  canGrow(): boolean;
23
- /** Réglage par défaut de toutes les instances créées ensuite par `make()` : `TextInput.configureUsing((input) => input.maxLength(255))`. */
23
+ /** Default configuration for every instance later created by `make()`: `TextInput.configureUsing((input) => input.maxLength(255))`. */
24
24
  static configureUsing<T>(this: abstract new (...args: any[]) => T, configure: (instance: T) => void): void;
25
25
  protected _name: string | null;
26
26
  protected _keyName: string | null;
@@ -33,32 +33,32 @@ export declare abstract class Component {
33
33
  hidden(condition?: Lazy<boolean, ComponentContext>): this;
34
34
  visible(condition?: Lazy<boolean, ComponentContext>): this;
35
35
  key(key: string | null): this;
36
- /** Masqué pour une opération donnée (`'create'`, `'edit'`…). */
36
+ /** Hidden for the given operation(s) (`'create'`, `'edit'`…). */
37
37
  hiddenOn(operations: string | string[]): this;
38
- /** Visible seulement pour une opération donnée. */
38
+ /** Visible only for the given operation(s). */
39
39
  visibleOn(operations: string | string[]): this;
40
- /** Comme Filament : un nombre vaut pour le point de rupture `lg` ; un objet remplace entièrement la valeur par défaut. Les valeurs peuvent être des closures. */
40
+ /** A number applies from the `lg` breakpoint; an object replaces the default entirely. Values may be closures. */
41
41
  columnSpan(span: ColumnSpan): this;
42
- /** Colonne de départ dans la grille, à partir du point de rupture `lg` (comme Filament). */
42
+ /** Starting grid column, from the `lg` breakpoint. */
43
43
  columnStart(start: number | null): this;
44
44
  extraAttributes(attributes: Record<string, string>): this;
45
45
  get livewire(): SchemaHost;
46
46
  isLiberatedFromContainerGrid(): boolean;
47
- /** Méthodes que le JavaScript du composant peut appeler côté serveur (annoncées au navigateur). */
47
+ /** Server methods the component's JavaScript may call (announced to the browser). */
48
48
  getExposedMethods(): string[];
49
- /** Faux pour une méthode exposée après laquelle le composant hôte doit être redessiné (étape suivante d'un assistant : erreurs de validation). */
49
+ /** False for an exposed method after which the host must re-render (e.g. next wizard step, to show validation errors). */
50
50
  isRenderlessMethod(_method: string): boolean;
51
51
  hasStatePath(): boolean;
52
- /** Clé absolue du composant : `<clé du schéma>.<clé ou nom>`, ou null. */
52
+ /** Absolute component key: `<schema key>.<key or name>`, or null. */
53
53
  getKey(): string | null;
54
54
  getLivewireKey(): string | null;
55
55
  getStatePath(): string;
56
56
  getAlpineScopeConfiguration(): Record<string, unknown>;
57
57
  context(): ComponentContext;
58
58
  isVisible(): Promise<boolean>;
59
- /** HTML propre au composant (sans son enveloppe de grille). */
59
+ /** The component's own HTML, without its grid wrapper. */
60
60
  abstract toHtml(): Promise<string>;
61
- /** Port de Component::toSchemaHtml : enveloppe de colonne de grille, rendue même si le composant est masqué. */
61
+ /** Grid column wrapper, rendered even when the component is hidden. */
62
62
  toSchemaHtml(isVisible: boolean): Promise<string>;
63
63
  }
64
64
  export declare class Schema {
@@ -85,22 +85,22 @@ export declare class Schema {
85
85
  inline(isInline?: boolean): this;
86
86
  operation(operation: string | null): this;
87
87
  record(record: unknown): this;
88
- /** Classe placée avant celles de la grille (ex. `fi-section-content`). */
88
+ /** Class placed before the grid classes (e.g. `fi-section-content`). */
89
89
  extraClass(name: string | null): this;
90
- /** Espacement resserré entre composants (`fi-sc-dense`). */
90
+ /** Tighter spacing between components (`fi-sc-dense`). */
91
91
  dense(condition?: boolean): this;
92
- /** Schéma rendu partiellement : sa racine porte `wire:partial="schema.<clé>"`. */
92
+ /** Partially rendered schema: its root carries `wire:partial="schema.<key>"`. */
93
93
  partiallyRendered(condition?: boolean): this;
94
94
  private _partialName;
95
- /** Nom du fragment `wire:partial` de la racine, quand il ne suit pas la clé du schéma (formulaire de filtres : `table-filters-form`). */
95
+ /** Root `wire:partial` name when it differs from the schema key (filters form: `table-filters-form`). */
96
96
  partialName(name: string | null): this;
97
97
  private _gap;
98
- /** `false` : composants accolés, sans espacement (`fi-sc-has-gap` absent), comme dans un FusedGroup. */
98
+ /** `false`: components touch, with no gap (no `fi-sc-has-gap`), as in a FusedGroup. */
99
99
  gap(condition?: boolean): this;
100
100
  private _fieldWrapperView;
101
101
  /**
102
- * Enveloppe des champs de ce schéma : `'filament-forms::plain-field-wrapper'` ne garde qu'un libellé réservé aux lecteurs d'écran
103
- * (champs d'un FusedGroup). `null` : l'enveloppe habituelle.
102
+ * Field wrapper for this schema: `'filament-forms::plain-field-wrapper'` keeps only a screen-reader label
103
+ * (FusedGroup fields). `null`: the usual wrapper.
104
104
  */
105
105
  fieldWrapperView(view: string | null): this;
106
106
  getFieldWrapperView(): string | null;
@@ -111,16 +111,15 @@ export declare class Schema {
111
111
  getRecord(): unknown;
112
112
  isInline(): boolean;
113
113
  isRoot(): boolean;
114
- /** Tous les champs à état, en profondeur. */
114
+ /** All components, depth-first. */
115
115
  getFlatComponents(): Component[];
116
- /** Les mêmes, sans les composants masqués ni leur descendance : un champ placé dans une section masquée n'est ni validé ni enregistré, comme dans Filament. */
116
+ /** Same, without hidden components or their descendants: a field inside a hidden section is neither validated nor saved. */
117
117
  getVisibleFlatComponents(): Promise<Component[]>;
118
- /** Port de Schema::renderEmbeddedHtml. */
119
118
  toHtml(): Promise<string>;
120
119
  }
121
- /** Schéma enfant d'un composant de mise en page : partage la clé et le chemin d'état du parent, sans être racine. */
120
+ /** Child schema of a layout component: shares the parent's key and state path, without being a root. */
122
121
  export declare function childSchema(parent: Component, components: Component[]): Schema;
123
- /** Groupe à état : ses enfants vivent sous `<chemin du conteneur>.<nom>` (utilisé par les formulaires de filtres). */
122
+ /** Stateful group: its children live under `<container path>.<name>` (used by filter forms). */
124
123
  export declare class StatefulGroup extends Component {
125
124
  private children;
126
125
  constructor(name: string, children: Component[]);
@@ -129,7 +128,7 @@ export declare class StatefulGroup extends Component {
129
128
  getChildSchemas(): Schema[];
130
129
  toHtml(): Promise<string>;
131
130
  }
132
- /** Regroupe des composants dans une grille, sans habillage (port de Group). */
131
+ /** Groups components in a grid, without any chrome. */
133
132
  export declare class Group extends Component {
134
133
  protected children: Component[];
135
134
  protected _columns: Record<string, number> | number | null;
@@ -140,14 +139,14 @@ export declare class Group extends Component {
140
139
  getChildSchemas(): Schema[];
141
140
  toHtml(): Promise<string>;
142
141
  }
143
- /** Grille de colonnes (port de Grid) : deux colonnes par défaut à partir de `lg`. */
142
+ /** Column grid: two columns from `lg` by default. */
144
143
  export declare class Grid extends Group {
145
144
  constructor(columns?: Record<string, number> | number);
146
145
  static make(columns?: Record<string, number> | number | Component[]): Grid;
147
146
  }
148
147
  /**
149
- * Composants côte à côte à partir d'un point de rupture (port de Flex) : chacun occupe la place disponible,
150
- * sauf ceux marqués `grow(false)`, qui gardent leur largeur naturelle.
148
+ * Components side by side from a breakpoint: each fills the available space,
149
+ * except those marked `grow(false)`, which keep their natural width.
151
150
  */
152
151
  export declare class Flex extends Component {
153
152
  private children;
@@ -160,7 +159,7 @@ export declare class Flex extends Component {
160
159
  toHtml(): Promise<string>;
161
160
  }
162
161
  export declare const slug: (text: string) => string;
163
- /** Section : carte regroupant des composants, avec un en-tête facultatif (titre, actions). Sans repli ni icône pour l'instant. */
162
+ /** Card grouping components, with an optional header (heading, actions). */
164
163
  export declare class Section extends Component {
165
164
  private children;
166
165
  private _columns;
@@ -172,19 +171,19 @@ export declare class Section extends Component {
172
171
  columns(columns: Record<string, number> | number | null): this;
173
172
  private _collapsible;
174
173
  private _collapsed;
175
- /** Section repliable par son en-tête ; `collapsed()` la replie d'emblée. */
174
+ /** Collapsible by clicking its header; `collapsed()` starts it collapsed. */
176
175
  collapsible(condition?: boolean): this;
177
176
  collapsed(condition?: boolean): this;
178
- /** Actions affichées à droite du titre. */
177
+ /** Actions shown to the right of the heading. */
179
178
  afterHeader(actions: Renderable[]): this;
180
- /** Actions que la section expose au montage. */
179
+ /** Actions the section exposes for mounting. */
181
180
  getActions(): Renderable[];
182
181
  getChildSchemas(): Schema[];
183
182
  toHtml(): Promise<string>;
184
183
  }
185
184
  /**
186
- * Balisage libre dans un schéma. Le contenu est inséré TEL QUEL : n'y placez jamais une valeur venue d'un utilisateur ou de la base
187
- * sans l'échapper avec `e()` de `@navette-js/support`.
185
+ * Raw markup in a schema. The content is inserted AS IS: never put a user- or database-supplied value in it
186
+ * without escaping it with `e()` from `@navette-js/support`.
188
187
  */
189
188
  export declare class Html extends Component {
190
189
  private content;
@@ -192,7 +191,7 @@ export declare class Html extends Component {
192
191
  static make(content: string | ((ctx: ComponentContext) => string | Promise<string>)): Html;
193
192
  toHtml(): Promise<string>;
194
193
  }
195
- /** Un onglet d'un composant Tabs : un titre, une icône facultative et son propre schéma (port de Tabs\Tab). */
194
+ /** A tab of a Tabs component: a label, an optional icon and its own schema. */
196
195
  export declare class Tab extends Component {
197
196
  private children;
198
197
  private _columns;
@@ -205,13 +204,12 @@ export declare class Tab extends Component {
205
204
  icon(name: string | null): this;
206
205
  getLabel(): string;
207
206
  getIcon(): string | null;
208
- /** Clé de l'onglet côté navigateur (sans le préfixe du schéma). */
209
- /** Clé de l'onglet dans son groupe : `::data::` suit le chemin d'état du schéma, absent d'un infolist (comme dans Filament). */
207
+ /** Browser-side tab key (no schema prefix): `::data::` follows the schema state path, and is dropped in infolists. */
210
208
  getTabKey(): string;
211
209
  getChildSchemas(): Schema[];
212
210
  toHtml(): Promise<string>;
213
211
  }
214
- /** Onglets de mise en page : tous les panneaux sont rendus, le navigateur n'affiche que l'onglet actif (port de Tabs). */
212
+ /** Layout tabs: every panel is rendered, the browser only shows the active one. */
215
213
  export declare class Tabs extends Component {
216
214
  private tabs;
217
215
  private label;
@@ -224,7 +222,7 @@ export declare class Tabs extends Component {
224
222
  getChildSchemas(): Schema[];
225
223
  toHtml(): Promise<string>;
226
224
  }
227
- /** Point d'injection d'un render hook, avec les portées du composant hôte. Libéré de la grille du conteneur. */
225
+ /** Render hook injection point, using the host's scopes. Liberated from the container grid. */
228
226
  export declare class RenderHook extends Component {
229
227
  private hook;
230
228
  constructor(hook: string);
@@ -232,14 +230,14 @@ export declare class RenderHook extends Component {
232
230
  isLiberatedFromContainerGrid(): boolean;
233
231
  toHtml(): Promise<string>;
234
232
  }
235
- /** Intègre un autre schéma du composant hôte (`form`, `infolist`…) comme schéma racine. */
233
+ /** Embeds another schema of the host (`form`, `infolist`…) as a root schema. */
236
234
  export declare class EmbeddedSchema extends Component {
237
235
  private schemaName;
238
236
  constructor(name: string);
239
237
  static make(name: string): EmbeddedSchema;
240
238
  toHtml(): Promise<string>;
241
239
  }
242
- /** Balise <form> : contenu, pied (actions), soumission vers une méthode du composant hôte. */
240
+ /** `<form>` element: content and footer (actions), submitted to a host method. */
243
241
  export declare class Form extends Component {
244
242
  private children;
245
243
  private _footer;
@@ -253,12 +251,12 @@ export declare class Form extends Component {
253
251
  getChildSchemas(): Schema[];
254
252
  toHtml(): Promise<string>;
255
253
  }
256
- /** Élément rendu dans un conteneur d'actions : en pratique une Action (paquet actions). */
254
+ /** Item rendered in an actions container: in practice an Action (actions package). */
257
255
  export interface Renderable {
258
256
  isVisible(ctx: ComponentContext): Promise<boolean>;
259
257
  toHtml(ctx: ComponentContext): Promise<string>;
260
258
  }
261
- /** Rangée d'actions d'un schéma. */
259
+ /** Row of actions in a schema. */
262
260
  export declare class Actions extends Component {
263
261
  private actions;
264
262
  private _fullWidth;
@@ -269,15 +267,15 @@ export declare class Actions extends Component {
269
267
  alignment(alignment: string | null): this;
270
268
  toHtml(): Promise<string>;
271
269
  }
272
- /** Gestionnaire de couleurs utilisé hors d'un panel ; dans un panel, celui du panel de l'hôte a la priorité. */
270
+ /** Color manager used outside a panel; inside a panel, the host panel's manager takes precedence. */
273
271
  export declare const useColorManager: (manager: ColorManager) => void;
274
- /** Élément d'une rangée en ligne : un composant de schéma ou une action. */
272
+ /** Item in an inline row: a schema component or an action. */
275
273
  export type InlineItem = Component | Renderable;
276
274
  /**
277
- * Rangée « en ligne » (port d'un schéma enfant `inline()` de Filament : pied, contrôles, après le libellé) où composants et actions se mêlent.
278
- * Les actions sont montées avec `schemaComponent: mountKey` (par défaut le schéma racine, qui les retrouve par `getActions()` du composant parent).
279
- * `actionView` : `'button'` (bouton plein), `'link'` (lien, ou bouton-icône pour une action `iconButton()`), `'auto'` (bouton-icône si `iconButton()`, bouton sinon).
280
- * `scope` remplace des clés de la configuration Alpine des composants (`path`, `containerPath`).
275
+ * Inline row mixing components and actions (footers, controls, after a label).
276
+ * Actions are mounted with `schemaComponent: mountKey` (the root schema by default, which finds them through the parent's `getActions()`).
277
+ * `actionView`: `'button'` (full button), `'link'` (link, or icon button for an `iconButton()` action), `'auto'` (icon button if `iconButton()`, button otherwise).
278
+ * `scope` overrides keys of the components' Alpine configuration (`path`, `containerPath`).
281
279
  */
282
280
  export declare function renderInlineItems(parent: Component, items: InlineItem[], options?: {
283
281
  alignment?: string | null;
@@ -286,8 +284,8 @@ export declare function renderInlineItems(parent: Component, items: InlineItem[]
286
284
  actionView?: 'button' | 'link' | 'auto';
287
285
  }): Promise<string>;
288
286
  /**
289
- * Cadre titré regroupant des champs (port de Fieldset) : une légende et une grille de deux colonnes par défaut.
290
- * Avec `statePath()`, les champs vivent sous ce chemin et le fieldset reçoit une clé (et un `id`).
287
+ * Titled frame grouping fields: a legend and a two-column grid by default.
288
+ * With `statePath()`, the fields live under that path and the fieldset gets a key (and an `id`).
291
289
  */
292
290
  export declare class Fieldset extends Component {
293
291
  private children;
@@ -301,21 +299,21 @@ export declare class Fieldset extends Component {
301
299
  schema(components: Component[]): this;
302
300
  columns(columns: Record<string, number> | number | null): this;
303
301
  label(label: Lazy<string | null, ComponentContext>): this;
304
- /** Légende gardée pour les lecteurs d'écran seulement. */
302
+ /** Keeps the legend for screen readers only. */
305
303
  hiddenLabel(condition?: boolean): this;
306
- /** `false` : sans bordure ni marge intérieure. */
304
+ /** `false`: no border or padding. */
307
305
  contained(condition?: boolean): this;
308
- /** Astérisque après la légende (le fieldset lui-même n'est jamais validé). */
306
+ /** Asterisk after the legend (the fieldset itself is never validated). */
309
307
  markAsRequired(condition?: boolean): this;
310
- /** Chemin d'état des champs, relatif au conteneur (port de `statePath()`). */
308
+ /** State path of the fields, relative to the container. */
311
309
  statePath(path: string | null): this;
312
310
  hasStatePath(): boolean;
313
311
  getChildSchemas(): Schema[];
314
312
  toHtml(): Promise<string>;
315
313
  }
316
314
  /**
317
- * Texte dans un schéma (port de Text) : simple `<span>`, ou pastille avec `badge()`. Le contenu est échappé ;
318
- * une `HtmlString` (de `@navette-js/support`) est insérée telle quelle, à ne construire qu'avec des valeurs échappées.
315
+ * Text in a schema: a plain `<span>`, or a badge with `badge()`. The content is escaped;
316
+ * an `HtmlString` (from `@navette-js/support`) is inserted as is, so build it only from escaped values.
319
317
  */
320
318
  export declare class Text extends Component {
321
319
  private _content;
@@ -335,22 +333,22 @@ export declare class Text extends Component {
335
333
  constructor(content: Lazy<string | HtmlString | null, ComponentContext>);
336
334
  static make(content: Lazy<string | HtmlString | null, ComponentContext>): Text;
337
335
  content(content: Lazy<string | HtmlString | null, ComponentContext>): this;
338
- /** Affiché en pastille. */
336
+ /** Renders as a badge. */
339
337
  badge(condition?: Lazy<boolean, ComponentContext>): this;
340
- /** Couleur (`gray` par défaut ; `primary`, `danger`…). */
338
+ /** Color (`gray` by default; `primary`, `danger`…). */
341
339
  color(color: Lazy<string | null, ComponentContext>): this;
342
- /** Taille du texte (`xs`, `sm`, `md`, `lg`) ou de la pastille. */
340
+ /** Text or badge size (`xs`, `sm`, `md`, `lg`). */
343
341
  size(size: string | null): this;
344
- /** Graisse (`bold`, `semibold`, `medium`…). */
342
+ /** Font weight (`bold`, `semibold`, `medium`…). */
345
343
  weight(weight: string | null): this;
346
- /** Famille de police (`sans`, `serif`, `mono`). */
344
+ /** Font family (`sans`, `serif`, `mono`). */
347
345
  fontFamily(family: string | null): this;
348
- /** Icône d'une pastille. */
346
+ /** Badge icon. */
349
347
  icon(name: string | null): this;
350
348
  iconPosition(position: 'before' | 'after'): this;
351
349
  iconSize(size: string | null): this;
352
350
  tooltip(text: Lazy<string | null, ComponentContext>): this;
353
- /** Un clic copie le texte (ou `copyableState()`) dans le presse-papiers. */
351
+ /** Clicking copies the text (or `copyableState()`) to the clipboard. */
354
352
  copyable(condition?: Lazy<boolean, ComponentContext>): this;
355
353
  copyableState(state: Lazy<string | null, ComponentContext>): this;
356
354
  copyMessage(message: string | null): this;
@@ -358,7 +356,7 @@ export declare class Text extends Component {
358
356
  getContent(): Promise<string | HtmlString | null>;
359
357
  toHtml(): Promise<string>;
360
358
  }
361
- /** Icône Heroicons dans un schéma (port de Icon) : décorative, sauf si une infobulle ou un `aria-label` (attributs supplémentaires) la décrit. */
359
+ /** Heroicon in a schema: decorative, unless a tooltip or an `aria-label` (extra attribute) describes it. */
362
360
  export declare class Icon extends Component {
363
361
  private _icon;
364
362
  private _color;
@@ -367,14 +365,14 @@ export declare class Icon extends Component {
367
365
  constructor(name: Lazy<string | null, ComponentContext>);
368
366
  static make(name: Lazy<string | null, ComponentContext>): Icon;
369
367
  icon(name: Lazy<string | null, ComponentContext>): this;
370
- /** Couleur (`primary` par défaut). */
368
+ /** Color (`primary` by default). */
371
369
  color(color: Lazy<string | null, ComponentContext>): this;
372
- /** Taille (`xs` … `2xl`) ; `base` revient à la taille par défaut. */
370
+ /** Size (`xs` … `2xl`); `base` resets to the default size. */
373
371
  size(size: string | null): this;
374
372
  tooltip(text: Lazy<string | null, ComponentContext>): this;
375
373
  toHtml(): Promise<string>;
376
374
  }
377
- /** Image dans un schéma (port de Image). Seules une adresse du site (`/…`) ou une adresse http(s) sont affichées. */
375
+ /** Image in a schema. Only same-site (`/…`) or http(s) URLs are rendered. */
378
376
  export declare class Image extends Component {
379
377
  private _url;
380
378
  private _alt;
@@ -387,11 +385,11 @@ export declare class Image extends Component {
387
385
  url(url: Lazy<string, ComponentContext>): this;
388
386
  alt(alt: Lazy<string, ComponentContext>): this;
389
387
  private static dimension;
390
- /** Hauteur (`8rem` par défaut) ; un nombre est en pixels. */
388
+ /** Height (`8rem` by default); a number is in pixels. */
391
389
  imageHeight(height: number | string | null): this;
392
390
  imageWidth(width: number | string | null): this;
393
391
  imageSize(size: number | string): this;
394
- /** Alignement (`start`, `center`, `end`). */
392
+ /** Alignment (`start`, `center`, `end`). */
395
393
  alignment(alignment: string | null): this;
396
394
  alignStart(): this;
397
395
  alignCenter(): this;
@@ -399,7 +397,7 @@ export declare class Image extends Component {
399
397
  tooltip(text: Lazy<string | null, ComponentContext>): this;
400
398
  toHtml(): Promise<string>;
401
399
  }
402
- /** Liste à puces (port de UnorderedList) : chaque élément est un composant ; une chaîne devient un `Text`. Deux colonnes à partir de `sm`. */
400
+ /** Bulleted list: each item is a component; a string becomes a `Text`. Two columns from `sm`. */
403
401
  export declare class UnorderedList extends Component {
404
402
  private children;
405
403
  private _columns;
@@ -409,12 +407,12 @@ export declare class UnorderedList extends Component {
409
407
  private static normalize;
410
408
  schema(items: (Component | string | HtmlString)[]): this;
411
409
  columns(columns: Record<string, number> | number | null): this;
412
- /** Taille du texte (`xs`, `sm`, `md`, `lg`). */
410
+ /** Text size (`xs`, `sm`, `md`, `lg`). */
413
411
  size(size: string | null): this;
414
412
  getChildSchemas(): Schema[];
415
413
  toHtml(): Promise<string>;
416
414
  }
417
- /** État vide (port de EmptyState) : icône, titre, description et un pied (actions, composants). */
415
+ /** Empty state: icon, heading, description and a footer (actions, components). */
418
416
  export declare class EmptyState extends Component {
419
417
  private _heading;
420
418
  private _description;
@@ -430,24 +428,24 @@ export declare class EmptyState extends Component {
430
428
  heading(heading: Lazy<string, ComponentContext>): this;
431
429
  description(description: Lazy<string | null, ComponentContext>): this;
432
430
  icon(name: string | null): this;
433
- /** Couleur de l'icône (`primary` par défaut). */
431
+ /** Icon color (`primary` by default). */
434
432
  iconColor(color: string | null): this;
435
433
  iconSize(size: string | null): this;
436
- /** Version resserrée. */
434
+ /** Compact variant. */
437
435
  compact(condition?: boolean): this;
438
- /** `false` : sans carte autour. */
436
+ /** `false`: no surrounding card. */
439
437
  contained(condition?: boolean): this;
440
- /** Balise du titre (`h2` par défaut). */
438
+ /** Heading tag (`h2` by default). */
441
439
  headingTag(tag: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'): this;
442
- /** Pied : actions et composants, en ligne. */
440
+ /** Footer: inline actions and components. */
443
441
  footer(items: InlineItem[]): this;
444
- /** Actions du pied, montées sur le schéma racine. */
442
+ /** Footer actions, mounted on the root schema. */
445
443
  getActions(): Renderable[];
446
444
  toHtml(): Promise<string>;
447
445
  }
448
446
  /**
449
- * Encadré d'information (port de Callout) : statut (`info()`, `success()`, `warning()`, `danger()`) qui fixe couleur et icône,
450
- * titre, description, actions de pied (en liens) et actions de contrôle (à droite).
447
+ * Information box: a status (`info()`, `success()`, `warning()`, `danger()`) setting color and icon,
448
+ * heading, description, footer actions (as links) and control actions (on the right).
451
449
  */
452
450
  export declare class Callout extends Component {
453
451
  private _heading;
@@ -466,36 +464,36 @@ export declare class Callout extends Component {
466
464
  static make(heading?: Lazy<string | null, ComponentContext>): Callout;
467
465
  heading(heading: Lazy<string | null, ComponentContext>): this;
468
466
  description(description: Lazy<string | null, ComponentContext>): this;
469
- /** Statut : couleur, icône et préfixe lu par les lecteurs d'écran (« Note: »…). */
467
+ /** Status: sets color, icon and a screen-reader prefix ("Note:"…). */
470
468
  status(status: string | null): this;
471
469
  danger(): this;
472
470
  info(): this;
473
471
  success(): this;
474
472
  warning(): this;
475
- /** Couleur du fond ; `null` retire celle du statut (l'icône la garde). */
473
+ /** Background color; `null` removes the status color (the icon keeps it). */
476
474
  color(color: string | null): this;
477
475
  icon(name: string | null): this;
478
476
  iconColor(color: string | null): this;
479
- /** Taille de l'icône (`lg` par défaut). */
477
+ /** Icon size (`lg` by default). */
480
478
  iconSize(size: string | null): this;
481
- /** Actions du pied, rendues en liens (port de `actions()` / `footerActions()`). */
479
+ /** Footer actions, rendered as links. */
482
480
  actions(actions: Renderable[]): this;
483
481
  footerActions(actions: Renderable[]): this;
484
- /** Alignement des actions du pied (`start`, `center`, `end`, `between`). */
482
+ /** Footer actions alignment (`start`, `center`, `end`, `between`). */
485
483
  footerActionsAlignment(alignment: string): this;
486
- /** Pied libre (composants et actions), à la place des actions de pied. */
484
+ /** Free-form footer (components and actions), replacing the footer actions. */
487
485
  footer(items: InlineItem[] | null): this;
488
- /** Actions à droite de l'encadré (fermeture…), en petite taille. */
486
+ /** Small actions on the right of the callout (dismiss…). */
489
487
  controlActions(actions: Renderable[]): this;
490
488
  getColor(): string | null;
491
489
  getIcon(): string | null;
492
- /** Actions de l'encadré, montées sur le schéma racine. */
490
+ /** Callout actions, mounted on the root schema. */
493
491
  getActions(): Renderable[];
494
492
  toHtml(): Promise<string>;
495
493
  }
496
494
  /**
497
- * Champs accolés sous un seul libellé (port de FusedGroup) : chaque champ n'a plus qu'un libellé pour lecteurs d'écran,
498
- * et la première erreur de validation des champs s'affiche sous le groupe.
495
+ * Fields joined under a single label: each field keeps only a screen-reader label,
496
+ * and the first validation error among the fields is shown under the group.
499
497
  */
500
498
  export declare class FusedGroup extends Component {
501
499
  private children;
@@ -509,10 +507,10 @@ export declare class FusedGroup extends Component {
509
507
  columns(columns: Record<string, number> | number | null): this;
510
508
  label(label: Lazy<string | null, ComponentContext>): this;
511
509
  hiddenLabel(condition?: boolean): this;
512
- /** Astérisque après le libellé (la validation reste celle de chaque champ). */
510
+ /** Asterisk after the label (validation stays per field). */
513
511
  markAsRequired(condition?: boolean): this;
514
512
  getChildSchemas(): Schema[];
515
- /** Première erreur des champs du groupe (y compris d'un élément d'un champ à valeurs multiples). */
513
+ /** First error among the group's fields (including one on an item of a multi-valued field). */
516
514
  private firstError;
517
515
  toHtml(): Promise<string>;
518
516
  }
package/lib/index.js CHANGED
@@ -1,5 +1,5 @@
1
- // @navette-js/schemas — port de filament/schemas : Schema, Component et premiers composants de mise en page.
2
- // Rendu en deux temps par composant : résolution asynchrone des propriétés, puis vue EJS synchrone (ADR 0003).
1
+ // @navette-js/schemas — Schema, Component and the layout components.
2
+ // Each component renders in two steps: async property resolution, then a synchronous EJS view (ADR 0003).
3
3
  import { Attributes, HtmlString, cls, e, evaluate, icon, js, renderHook, views, configured, configureUsing } from '@navette-js/support';
4
4
  import { t } from '@navette-js/support/i18n';
5
5
  import { fileURLToPath } from 'node:url';
@@ -7,10 +7,10 @@ import { createHash } from 'node:crypto';
7
7
  views.namespace('filament-schemas', fileURLToPath(new URL('../views', import.meta.url)));
8
8
  export class Component {
9
9
  _grow = true;
10
- /** Dans un Flex : `false` pour garder la largeur naturelle au lieu d'occuper la place disponible. */
10
+ /** Inside a Flex: `false` keeps the natural width instead of filling the available space. */
11
11
  grow(condition = true) { this._grow = condition; return this; }
12
12
  canGrow() { return this._grow; }
13
- /** Réglage par défaut de toutes les instances créées ensuite par `make()` : `TextInput.configureUsing((input) => input.maxLength(255))`. */
13
+ /** Default configuration for every instance later created by `make()`: `TextInput.configureUsing((input) => input.maxLength(255))`. */
14
14
  static configureUsing(configure) { configureUsing(this, configure); }
15
15
  _name = null;
16
16
  _keyName = null;
@@ -23,28 +23,28 @@ export class Component {
23
23
  hidden(condition = true) { this._hidden = condition; return this; }
24
24
  visible(condition = true) { this._visible = condition; return this; }
25
25
  key(key) { this._keyName = key; return this; }
26
- /** Masqué pour une opération donnée (`'create'`, `'edit'`…). */
26
+ /** Hidden for the given operation(s) (`'create'`, `'edit'`…). */
27
27
  hiddenOn(operations) { const list = [].concat(operations); return this.hidden(({ operation }) => operation !== null && list.includes(operation)); }
28
- /** Visible seulement pour une opération donnée. */
28
+ /** Visible only for the given operation(s). */
29
29
  visibleOn(operations) { const list = [].concat(operations); return this.visible(({ operation }) => operation !== null && list.includes(operation)); }
30
- /** Comme Filament : un nombre vaut pour le point de rupture `lg` ; un objet remplace entièrement la valeur par défaut. Les valeurs peuvent être des closures. */
30
+ /** A number applies from the `lg` breakpoint; an object replaces the default entirely. Values may be closures. */
31
31
  columnSpan(span) { this._columnSpan = typeof span === 'object' ? span : { default: 1, lg: span }; return this; }
32
32
  columnSpanFull() { this._columnSpan = { default: 'full' }; return this; }
33
- /** Colonne de départ dans la grille, à partir du point de rupture `lg` (comme Filament). */
33
+ /** Starting grid column, from the `lg` breakpoint. */
34
34
  columnStart(start) { this._columnStart = start; return this; }
35
- /** Toute la largeur de la grille, quel que soit l'écran (`columnSpan('full')` ne vaut qu'à partir de `lg`). */
35
+ /** Full grid width on every screen size (`columnSpan('full')` only applies from `lg`). */
36
36
  columnSpanFull() { return this.columnSpan({ default: 'full' }); }
37
37
  extraAttributes(attributes) { Object.assign(this._extraAttributes, attributes); return this; }
38
38
  get livewire() { return this.container.livewire; }
39
39
  isLiberatedFromContainerGrid() { return false; }
40
- /** Méthodes que le JavaScript du composant peut appeler côté serveur (annoncées au navigateur). */
40
+ /** Server methods the component's JavaScript may call (announced to the browser). */
41
41
  getExposedMethods() { return []; }
42
- /** Faux pour une méthode exposée après laquelle le composant hôte doit être redessiné (étape suivante d'un assistant : erreurs de validation). */
42
+ /** False for an exposed method after which the host must re-render (e.g. next wizard step, to show validation errors). */
43
43
  isRenderlessMethod(_method) { return true; }
44
44
  hasStatePath() { return false; }
45
- /** Clé absolue du composant : `<clé du schéma>.<clé ou nom>`, ou null. */
45
+ /** Absolute component key: `<schema key>.<key or name>`, or null. */
46
46
  getKey() {
47
- // `::data::` dans une clé générée (section, onglets) tient lieu du chemin d'état du schéma : absent sans chemin (infolist), comme dans Filament.
47
+ // `::data::` in a generated key (section, tabs) stands for the schema state path, and is dropped when there is none (infolists).
48
48
  const statePath = this.container.getStatePath();
49
49
  const own = (this._keyName ?? this._name)?.replace('::data::', statePath ? `::${statePath}::` : '::') ?? null;
50
50
  return own === null ? null : `${this.container.getKey()}.${own}`;
@@ -52,7 +52,7 @@ export class Component {
52
52
  getLivewireKey() { const k = this.getKey(); return k === null ? null : `${this.livewire.id}.${k}`; }
53
53
  getStatePath() { return this.hasStatePath() ? [this.container.getStatePath(), this._name].filter(Boolean).join('.') : ''; }
54
54
  getAlpineScopeConfiguration() {
55
- // Un composant sans état propre (mise en page) expose le chemin d'état de son conteneur.
55
+ // A stateless (layout) component exposes its container's state path.
56
56
  return { key: this.getKey(), exposedMethods: this.getExposedMethods(), path: this.hasStatePath() ? this.getStatePath() : this.container.getStatePath(), containerPath: this.container.getStatePath() };
57
57
  }
58
58
  context() {
@@ -64,7 +64,7 @@ export class Component {
64
64
  const ctx = this.context();
65
65
  return !(await evaluate(this._hidden, ctx)) && (await evaluate(this._visible, ctx));
66
66
  }
67
- /** Port de Component::toSchemaHtml : enveloppe de colonne de grille, rendue même si le composant est masqué. */
67
+ /** Grid column wrapper, rendered even when the component is hidden. */
68
68
  async toSchemaHtml(isVisible) {
69
69
  const key = this.getKey();
70
70
  const span = {};
@@ -107,22 +107,22 @@ export class Schema {
107
107
  inline(isInline = true) { this._inline = isInline; return this; }
108
108
  operation(operation) { this._operation = operation; return this; }
109
109
  record(record) { this._record = record; return this; }
110
- /** Classe placée avant celles de la grille (ex. `fi-section-content`). */
110
+ /** Class placed before the grid classes (e.g. `fi-section-content`). */
111
111
  extraClass(name) { this._extraClass = name; return this; }
112
- /** Espacement resserré entre composants (`fi-sc-dense`). */
112
+ /** Tighter spacing between components (`fi-sc-dense`). */
113
113
  dense(condition = true) { this._dense = condition; return this; }
114
- /** Schéma rendu partiellement : sa racine porte `wire:partial="schema.<clé>"`. */
114
+ /** Partially rendered schema: its root carries `wire:partial="schema.<key>"`. */
115
115
  partiallyRendered(condition = true) { this._partial = condition; return this; }
116
116
  _partialName = null;
117
- /** Nom du fragment `wire:partial` de la racine, quand il ne suit pas la clé du schéma (formulaire de filtres : `table-filters-form`). */
117
+ /** Root `wire:partial` name when it differs from the schema key (filters form: `table-filters-form`). */
118
118
  partialName(name) { this._partialName = name; return this; }
119
119
  _gap = true;
120
- /** `false` : composants accolés, sans espacement (`fi-sc-has-gap` absent), comme dans un FusedGroup. */
120
+ /** `false`: components touch, with no gap (no `fi-sc-has-gap`), as in a FusedGroup. */
121
121
  gap(condition = true) { this._gap = condition; return this; }
122
122
  _fieldWrapperView = null;
123
123
  /**
124
- * Enveloppe des champs de ce schéma : `'filament-forms::plain-field-wrapper'` ne garde qu'un libellé réservé aux lecteurs d'écran
125
- * (champs d'un FusedGroup). `null` : l'enveloppe habituelle.
124
+ * Field wrapper for this schema: `'filament-forms::plain-field-wrapper'` keeps only a screen-reader label
125
+ * (FusedGroup fields). `null`: the usual wrapper.
126
126
  */
127
127
  fieldWrapperView(view) { this._fieldWrapperView = view; return this; }
128
128
  getFieldWrapperView() { return this._fieldWrapperView; }
@@ -133,11 +133,11 @@ export class Schema {
133
133
  getRecord() { return this._record; }
134
134
  isInline() { return this._inline; }
135
135
  isRoot() { return this._root; }
136
- /** Tous les champs à état, en profondeur. */
136
+ /** All components, depth-first. */
137
137
  getFlatComponents() {
138
138
  return this._components.flatMap((c) => [c, ...(c.getChildSchemas?.() ?? []).flatMap((s) => s.getFlatComponents())]);
139
139
  }
140
- /** Les mêmes, sans les composants masqués ni leur descendance : un champ placé dans une section masquée n'est ni validé ni enregistré, comme dans Filament. */
140
+ /** Same, without hidden components or their descendants: a field inside a hidden section is neither validated nor saved. */
141
141
  async getVisibleFlatComponents() {
142
142
  const out = [];
143
143
  for (const c of this._components) {
@@ -149,7 +149,6 @@ export class Schema {
149
149
  }
150
150
  return out;
151
151
  }
152
- /** Port de Schema::renderEmbeddedHtml. */
153
152
  async toHtml() {
154
153
  const withVisibility = await Promise.all(this._components.map(async (c) => [c, await c.isVisible()]));
155
154
  if (!withVisibility.some(([, v]) => v))
@@ -173,12 +172,12 @@ export class Schema {
173
172
  return `<div ${attributes.toHtml()}>${parts.join('')}</div>`;
174
173
  }
175
174
  }
176
- /** Schéma enfant d'un composant de mise en page : partage la clé et le chemin d'état du parent, sans être racine. */
175
+ /** Child schema of a layout component: shares the parent's key and state path, without being a root. */
177
176
  export function childSchema(parent, components) {
178
177
  const c = parent.container;
179
178
  return new Schema(c.livewire).key(c.getKey()).statePath(c.getStatePath() || null).operation(c.getOperation()).record(c.getRecord()).root(false).components(components);
180
179
  }
181
- /** Groupe à état : ses enfants vivent sous `<chemin du conteneur>.<nom>` (utilisé par les formulaires de filtres). */
180
+ /** Stateful group: its children live under `<container path>.<name>` (used by filter forms). */
182
181
  export class StatefulGroup extends Component {
183
182
  children;
184
183
  constructor(name, children) { super(); this._name = name; this.children = children; }
@@ -190,7 +189,7 @@ export class StatefulGroup extends Component {
190
189
  }
191
190
  async toHtml() { return `<div id="${e(this.getKey())}">${await this.getChildSchemas()[0].toHtml()}</div>`; }
192
191
  }
193
- /** Regroupe des composants dans une grille, sans habillage (port de Group). */
192
+ /** Groups components in a grid, without any chrome. */
194
193
  export class Group extends Component {
195
194
  children;
196
195
  _columns = {};
@@ -201,14 +200,14 @@ export class Group extends Component {
201
200
  getChildSchemas() { return [childSchema(this, this.children).columns(this._columns)]; }
202
201
  async toHtml() { return `<div>${await this.getChildSchemas()[0].toHtml()}</div>`; }
203
202
  }
204
- /** Grille de colonnes (port de Grid) : deux colonnes par défaut à partir de `lg`. */
203
+ /** Column grid: two columns from `lg` by default. */
205
204
  export class Grid extends Group {
206
205
  constructor(columns = 2) { super(); this._columns = columns; }
207
206
  static make(columns = 2) { return configured(new Grid(Array.isArray(columns) ? 2 : columns)); }
208
207
  }
209
208
  /**
210
- * Composants côte à côte à partir d'un point de rupture (port de Flex) : chacun occupe la place disponible,
211
- * sauf ceux marqués `grow(false)`, qui gardent leur largeur naturelle.
209
+ * Components side by side from a breakpoint: each fills the available space,
210
+ * except those marked `grow(false)`, which keep their natural width.
212
211
  */
213
212
  export class Flex extends Component {
214
213
  children;
@@ -229,7 +228,7 @@ export class Flex extends Component {
229
228
  }
230
229
  }
231
230
  export const slug = (text) => text.toLowerCase().normalize('NFD').replace(/[\u0300-\u036f]/g, '').replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
232
- /** Section : carte regroupant des composants, avec un en-tête facultatif (titre, actions). Sans repli ni icône pour l'instant. */
231
+ /** Card grouping components, with an optional header (heading, actions). */
233
232
  export class Section extends Component {
234
233
  children = [];
235
234
  _columns = {};
@@ -238,7 +237,7 @@ export class Section extends Component {
238
237
  constructor(heading = null) {
239
238
  super();
240
239
  this._heading = heading;
241
- // Comme Filament : une section titrée a une clé dérivée de son titre.
240
+ // A section with a heading gets a key derived from it.
242
241
  if (heading !== null)
243
242
  this._keyName = `${slug(heading)}::data::section`;
244
243
  }
@@ -247,13 +246,13 @@ export class Section extends Component {
247
246
  columns(columns) { this._columns = columns; return this; }
248
247
  _collapsible = false;
249
248
  _collapsed = false;
250
- /** Section repliable par son en-tête ; `collapsed()` la replie d'emblée. */
249
+ /** Collapsible by clicking its header; `collapsed()` starts it collapsed. */
251
250
  collapsible(condition = true) { this._collapsible = condition; return this; }
252
251
  collapsed(condition = true) { this._collapsed = condition; if (condition)
253
252
  this._collapsible = true; return this; }
254
- /** Actions affichées à droite du titre. */
253
+ /** Actions shown to the right of the heading. */
255
254
  afterHeader(actions) { this._afterHeader = actions; return this; }
256
- /** Actions que la section expose au montage. */
255
+ /** Actions the section exposes for mounting. */
257
256
  getActions() { return this._afterHeader; }
258
257
  getChildSchemas() { return [childSchema(this, this.children).columns(this._columns).extraClass('fi-section-content')]; }
259
258
  async toHtml() {
@@ -266,12 +265,12 @@ export class Section extends Component {
266
265
  const key = this.getKey();
267
266
  const ctx = this.context();
268
267
  const after = [];
269
- // Contexte de montage : celui de l'hôte, plus le schéma auquel la section appartient (comme Filament).
268
+ // Mount context: the host's, plus the schema the section belongs to.
270
269
  const mountContext = { ...(this.livewire.getActionMountContext?.() ?? {}), schemaComponent: this.container.getKey() };
271
270
  for (const action of this._afterHeader)
272
271
  if (await action.isVisible(ctx))
273
272
  after.push(`<div class="fi-sc-action">${await action.toHtml(ctx, mountContext)}</div>`);
274
- // Section repliable : événements `collapse-section` / `expand-section`… et bouton dans l'en-tête (port de filament::components.section).
273
+ // Collapsible section: listens to `collapse-section` / `expand-section`… window events, with a toggle button in the header.
275
274
  const idTest = `if ($event.detail.id == (${js(key)} ?? $el.id))`;
276
275
  const collapse = this._collapsible ? ` x-on:collapse-section.window="${e(`${idTest} isCollapsed = true`)}" x-on:expand="isCollapsed = false" x-on:expand-section.window="${e(`${idTest} isCollapsed = false`)}" x-on:open-section.window="${e(`${idTest} isCollapsed = false`)}" x-on:toggle-section.window="${e(`${idTest} isCollapsed = ! isCollapsed`)}" x-on:reset-schema-component-state.window="${e(`if (($event.detail.livewireId === ${js(this.livewire.id)}) && ($event.detail.schemaKey === ${js(key.split('.')[0])})) $nextTick(() => isCollapsed = ${this._collapsed ? 'true' : 'false'})`)}" x-bind:class="isCollapsed &amp;&amp; 'fi-collapsed'"` : '';
277
276
  const collapseButton = this._collapsible ? `<button type="button" x-on:click.stop="isCollapsed = ! isCollapsed" aria-label="${e(t(this._collapsed ? 'filament::components/section.actions.expand.label' : 'filament::components/section.actions.collapse.label'))}" x-bind:aria-label="isCollapsed ? ${e(js(t('filament::components/section.actions.expand.label')))} : ${e(js(t('filament::components/section.actions.collapse.label')))}" aria-expanded="${this._collapsed ? 'false' : 'true'}" x-bind:aria-expanded="(! isCollapsed).toString()" aria-controls="${e(key)}-content" class="fi-icon-btn fi-size-md fi-section-collapse-btn">${icon('m-chevron-up')}</button>` : '';
@@ -281,8 +280,8 @@ export class Section extends Component {
281
280
  }
282
281
  }
283
282
  /**
284
- * Balisage libre dans un schéma. Le contenu est inséré TEL QUEL : n'y placez jamais une valeur venue d'un utilisateur ou de la base
285
- * sans l'échapper avec `e()` de `@navette-js/support`.
283
+ * Raw markup in a schema. The content is inserted AS IS: never put a user- or database-supplied value in it
284
+ * without escaping it with `e()` from `@navette-js/support`.
286
285
  */
287
286
  export class Html extends Component {
288
287
  content;
@@ -290,7 +289,7 @@ export class Html extends Component {
290
289
  static make(content) { return new Html(content); }
291
290
  async toHtml() { return typeof this.content === 'function' ? this.content(this.context()) : this.content; }
292
291
  }
293
- /** Un onglet d'un composant Tabs : un titre, une icône facultative et son propre schéma (port de Tabs\Tab). */
292
+ /** A tab of a Tabs component: a label, an optional icon and its own schema. */
294
293
  export class Tab extends Component {
295
294
  children = [];
296
295
  _columns = {};
@@ -303,13 +302,12 @@ export class Tab extends Component {
303
302
  icon(name) { this._icon = name; return this; }
304
303
  getLabel() { return this.label; }
305
304
  getIcon() { return this._icon; }
306
- /** Clé de l'onglet côté navigateur (sans le préfixe du schéma). */
307
- /** Clé de l'onglet dans son groupe : `::data::` suit le chemin d'état du schéma, absent d'un infolist (comme dans Filament). */
305
+ /** Browser-side tab key (no schema prefix): `::data::` follows the schema state path, and is dropped in infolists. */
308
306
  getTabKey() { const statePath = this.container.getStatePath(); return this._keyName.replace('::data::', statePath ? `::${statePath}::` : '::'); }
309
307
  getChildSchemas() { return [childSchema(this, this.children).columns(this._columns)]; }
310
308
  async toHtml() { return this.getChildSchemas()[0].toHtml(); }
311
309
  }
312
- /** Onglets de mise en page : tous les panneaux sont rendus, le navigateur n'affiche que l'onglet actif (port de Tabs). */
310
+ /** Layout tabs: every panel is rendered, the browser only shows the active one. */
313
311
  export class Tabs extends Component {
314
312
  tabs = [];
315
313
  label;
@@ -321,7 +319,7 @@ export class Tabs extends Component {
321
319
  getDeferredTabBadges() { return {}; }
322
320
  getChildSchemas() { return [childSchema(this, this.tabs)]; }
323
321
  async toHtml() {
324
- // Le schéma enfant rattache les onglets à leur conteneur : c'est lui qui donne leurs clés.
322
+ // Building the child schema attaches the tabs to their container, which is what gives them their keys.
325
323
  this.getChildSchemas();
326
324
  const key = this.getKey();
327
325
  const id = this.livewire.id;
@@ -358,7 +356,7 @@ export class Tabs extends Component {
358
356
  })" x-load x-load-src="${e(views.render('filament-schemas::asset', { path: 'tabs' }).trim())}" wire:ignore.self id="${e(key)}" wire:key="${e(`${id}.${key}`)}.container" class="fi-sc-tabs fi-contained"><div x-cloak="x-cloak" x-ref="tabsHeader" class="fi-tabs fi-contained"><div x-ref="tablist" role="tablist" x-bind:role="hasVisibleTabHeaders ? 'tablist' : 'group'" aria-label="${e(this.label)}" x-on:keydown="handleKeydown($event)" class="fi-sc-tabs-tablist">${buttons.join('')}</div></div>${panels.join('')}</div>`;
359
357
  }
360
358
  }
361
- /** Point d'injection d'un render hook, avec les portées du composant hôte. Libéré de la grille du conteneur. */
359
+ /** Render hook injection point, using the host's scopes. Liberated from the container grid. */
362
360
  export class RenderHook extends Component {
363
361
  hook;
364
362
  constructor(hook) { super(); this.hook = hook; }
@@ -366,14 +364,14 @@ export class RenderHook extends Component {
366
364
  isLiberatedFromContainerGrid() { return true; }
367
365
  async toHtml() { return renderHook(this.hook, this.livewire.getRenderHookScopes?.() ?? []); }
368
366
  }
369
- /** Intègre un autre schéma du composant hôte (`form`, `infolist`…) comme schéma racine. */
367
+ /** Embeds another schema of the host (`form`, `infolist`…) as a root schema. */
370
368
  export class EmbeddedSchema extends Component {
371
369
  schemaName;
372
370
  constructor(name) { super(); this.schemaName = name; }
373
371
  static make(name) { return configured(new EmbeddedSchema(name)); }
374
372
  async toHtml() { return (await this.livewire.getSchema(this.schemaName)).toHtml(); }
375
373
  }
376
- /** Balise <form> : contenu, pied (actions), soumission vers une méthode du composant hôte. */
374
+ /** `<form>` element: content and footer (actions), submitted to a host method. */
377
375
  export class Form extends Component {
378
376
  children;
379
377
  _footer = [];
@@ -391,7 +389,7 @@ export class Form extends Component {
391
389
  return `<form ${attributes.toHtml()}>${await content.toHtml()}${await footer.toHtml()}</form>`;
392
390
  }
393
391
  }
394
- /** Rangée d'actions d'un schéma. */
392
+ /** Row of actions in a schema. */
395
393
  export class Actions extends Component {
396
394
  actions;
397
395
  _fullWidth = false;
@@ -412,24 +410,23 @@ export class Actions extends Component {
412
410
  return `<div ${new Attributes().merge({ id: this.getKey() }).class(['fi-sc-actions']).toHtml()}><div class="${inner}">${visible.join('')}</div></div>`;
413
411
  }
414
412
  }
415
- // ------------------------------------------------------------------ couleurs, infobulles et rangées « en ligne »
416
413
  let colorManager = null;
417
- /** Gestionnaire de couleurs utilisé hors d'un panel ; dans un panel, celui du panel de l'hôte a la priorité. */
414
+ /** Color manager used outside a panel; inside a panel, the host panel's manager takes precedence. */
418
415
  export const useColorManager = (manager) => { colorManager = manager; };
419
416
  const colorsFor = (component) => component.livewire?.panel?.colors ?? colorManager;
420
- /** Couleur sans nuance calculée (icône, callout, état vide) : rien pour le gris, comme les composants `HasDefaultGrayColor` de Filament. */
417
+ /** Color classes without computed shades (icon, callout, empty state); none for gray, the default. */
421
418
  const plainColorClasses = (color) => (color && color !== 'gray' ? ['fi-color', `fi-color-${color.replace(/[^a-zA-Z0-9_-]/g, '')}`] : []);
422
- /** Classe de taille ou de graisse : seuls les caractères d'un nom de classe sont gardés. */
419
+ /** Size or weight class: only class-name characters are kept. */
423
420
  const safeClass = (value) => (value ? value.replace(/[^a-zA-Z0-9_:-]/g, '') || null : null);
424
421
  const tooltipExpression = (text) => (text ? `{ content: ${js(text)}, theme: $store.theme, allowHTML: false }` : null);
425
422
  const isBlank = (value) => value === null || value === undefined || (typeof value === 'string' && value.trim() === '') || (value instanceof HtmlString && value.html.trim() === '');
426
- /** Texte échappé, ou HTML d'une `HtmlString` inséré tel quel (à ne construire qu'avec des valeurs échappées). */
423
+ /** Escaped text, or an `HtmlString`'s HTML inserted as is (build it only from escaped values). */
427
424
  const textOrHtml = (value) => (value instanceof HtmlString ? value.html : e(value));
428
425
  /**
429
- * Rangée « en ligne » (port d'un schéma enfant `inline()` de Filament : pied, contrôles, après le libellé) où composants et actions se mêlent.
430
- * Les actions sont montées avec `schemaComponent: mountKey` (par défaut le schéma racine, qui les retrouve par `getActions()` du composant parent).
431
- * `actionView` : `'button'` (bouton plein), `'link'` (lien, ou bouton-icône pour une action `iconButton()`), `'auto'` (bouton-icône si `iconButton()`, bouton sinon).
432
- * `scope` remplace des clés de la configuration Alpine des composants (`path`, `containerPath`).
426
+ * Inline row mixing components and actions (footers, controls, after a label).
427
+ * Actions are mounted with `schemaComponent: mountKey` (the root schema by default, which finds them through the parent's `getActions()`).
428
+ * `actionView`: `'button'` (full button), `'link'` (link, or icon button for an `iconButton()` action), `'auto'` (icon button if `iconButton()`, button otherwise).
429
+ * `scope` overrides keys of the components' Alpine configuration (`path`, `containerPath`).
433
430
  */
434
431
  export async function renderInlineItems(parent, items, options = {}) {
435
432
  const components = items.filter((item) => item instanceof Component);
@@ -456,7 +453,7 @@ export async function renderInlineItems(parent, items, options = {}) {
456
453
  const action = item;
457
454
  const view = options.actionView ?? 'button';
458
455
  const asLink = typeof action.toLinkHtml === 'function' && (view === 'link' || (view === 'auto' && action._iconButton === true));
459
- // Le rendu « lien » des actions sert aussi aux lignes de table : sa clé de ligne, vide ici, est retirée.
456
+ // The link rendering is shared with table rows: its row key, empty here, is stripped.
460
457
  const html = asLink ? String(await action.toLinkHtml(ctx, mountContext, '')).replace(' wire:key=""', '') : await action.toHtml(ctx, mountContext);
461
458
  parts.push(`<div class="fi-sc-action">${html}</div>`);
462
459
  }
@@ -464,9 +461,9 @@ export async function renderInlineItems(parent, items, options = {}) {
464
461
  return '';
465
462
  return `<div class="${cls(['fi-sc', 'fi-inline', options.alignment ? `fi-align-${options.alignment}` : null, 'fi-sc-has-gap', 'fi-sc-dense'])}">${parts.join('')}</div>`;
466
463
  }
467
- /** Actions d'une liste d'éléments en ligne (à exposer par `getActions()` pour qu'elles puissent être montées). */
464
+ /** Actions among inline items (expose them through `getActions()` so they can be mounted). */
468
465
  const actionsOf = (items) => items.filter((item) => !(item instanceof Component));
469
- /** Grille « en colonnes » (port de `grid($columns, GridDirection::Column)`) : les éléments se remplissent colonne par colonne. */
466
+ /** Column-direction grid: items fill column by column. */
470
467
  function columnGrid(columns) {
471
468
  const cols = typeof columns === 'number' ? { lg: columns } : { ...(columns ?? {}) };
472
469
  for (const key of Object.keys(cols))
@@ -479,8 +476,8 @@ function columnGrid(columns) {
479
476
  .style(Object.entries(cols).map(([breakpoint, count]) => `--cols-${name(breakpoint)}: ${count}`));
480
477
  }
481
478
  /**
482
- * Cadre titré regroupant des champs (port de Fieldset) : une légende et une grille de deux colonnes par défaut.
483
- * Avec `statePath()`, les champs vivent sous ce chemin et le fieldset reçoit une clé (et un `id`).
479
+ * Titled frame grouping fields: a legend and a two-column grid by default.
480
+ * With `statePath()`, the fields live under that path and the fieldset gets a key (and an `id`).
484
481
  */
485
482
  export class Fieldset extends Component {
486
483
  children = [];
@@ -494,13 +491,13 @@ export class Fieldset extends Component {
494
491
  schema(components) { this.children = components; return this; }
495
492
  columns(columns) { this._columns = columns; return this; }
496
493
  label(label) { this._label = label; return this; }
497
- /** Légende gardée pour les lecteurs d'écran seulement. */
494
+ /** Keeps the legend for screen readers only. */
498
495
  hiddenLabel(condition = true) { this._hiddenLabel = condition; return this; }
499
- /** `false` : sans bordure ni marge intérieure. */
496
+ /** `false`: no border or padding. */
500
497
  contained(condition = true) { this._contained = condition; return this; }
501
- /** Astérisque après la légende (le fieldset lui-même n'est jamais validé). */
498
+ /** Asterisk after the legend (the fieldset itself is never validated). */
502
499
  markAsRequired(condition = true) { this._markedAsRequired = condition; return this; }
503
- /** Chemin d'état des champs, relatif au conteneur (port de `statePath()`). */
500
+ /** State path of the fields, relative to the container. */
504
501
  statePath(path) { this._name = path; return this; }
505
502
  hasStatePath() { return this._name !== null; }
506
503
  getChildSchemas() {
@@ -518,8 +515,8 @@ export class Fieldset extends Component {
518
515
  }
519
516
  }
520
517
  /**
521
- * Texte dans un schéma (port de Text) : simple `<span>`, ou pastille avec `badge()`. Le contenu est échappé ;
522
- * une `HtmlString` (de `@navette-js/support`) est insérée telle quelle, à ne construire qu'avec des valeurs échappées.
518
+ * Text in a schema: a plain `<span>`, or a badge with `badge()`. The content is escaped;
519
+ * an `HtmlString` (from `@navette-js/support`) is inserted as is, so build it only from escaped values.
523
520
  */
524
521
  export class Text extends Component {
525
522
  _content;
@@ -539,22 +536,22 @@ export class Text extends Component {
539
536
  constructor(content) { super(); this._content = content; }
540
537
  static make(content) { return configured(new Text(content)); }
541
538
  content(content) { this._content = content; return this; }
542
- /** Affiché en pastille. */
539
+ /** Renders as a badge. */
543
540
  badge(condition = true) { this._badge = condition; return this; }
544
- /** Couleur (`gray` par défaut ; `primary`, `danger`…). */
541
+ /** Color (`gray` by default; `primary`, `danger`…). */
545
542
  color(color) { this._color = color; return this; }
546
- /** Taille du texte (`xs`, `sm`, `md`, `lg`) ou de la pastille. */
543
+ /** Text or badge size (`xs`, `sm`, `md`, `lg`). */
547
544
  size(size) { this._size = size; return this; }
548
- /** Graisse (`bold`, `semibold`, `medium`…). */
545
+ /** Font weight (`bold`, `semibold`, `medium`…). */
549
546
  weight(weight) { this._weight = weight; return this; }
550
- /** Famille de police (`sans`, `serif`, `mono`). */
547
+ /** Font family (`sans`, `serif`, `mono`). */
551
548
  fontFamily(family) { this._fontFamily = family; return this; }
552
- /** Icône d'une pastille. */
549
+ /** Badge icon. */
553
550
  icon(name) { this._icon = name; return this; }
554
551
  iconPosition(position) { this._iconPosition = position; return this; }
555
552
  iconSize(size) { this._iconSize = size; return this; }
556
553
  tooltip(text) { this._tooltip = text; return this; }
557
- /** Un clic copie le texte (ou `copyableState()`) dans le presse-papiers. */
554
+ /** Clicking copies the text (or `copyableState()`) to the clipboard. */
558
555
  copyable(condition = true) { this._copyable = condition; return this; }
559
556
  copyableState(state) { this._copyableState = state; return this; }
560
557
  copyMessage(message) { this._copyMessage = message; return this; }
@@ -575,7 +572,7 @@ export class Text extends Component {
575
572
  const iconHtml = this._icon ? icon(this._icon, { size: safeClass(this._iconSize) ?? 'sm' }) : '';
576
573
  return `<${tag} ${attributes.toHtml()}>${this._iconPosition === 'before' ? iconHtml : ''}<span class="fi-badge-label-ctn"><span class="fi-badge-label">${textOrHtml(content)}</span></span>${this._iconPosition === 'after' ? iconHtml : ''}</${tag}>`;
577
574
  }
578
- // Couleur du texte : même recherche de contraste que celle d'un lien (TextComponent de Filament).
575
+ // Text color: same contrast-aware classes as a link.
579
576
  const colorClasses = color !== 'gray' ? (colorsFor(this)?.getComponentClasses('link', color) ?? plainColorClasses(color)) : [];
580
577
  const attributes = new Attributes().merge({
581
578
  role: isCopyable ? 'button' : null, tabindex: isCopyable ? '0' : null, 'x-on:click': isCopyable ? copy : null,
@@ -585,7 +582,7 @@ export class Text extends Component {
585
582
  return `<span ${attributes.toHtml()}>${textOrHtml(content)}</span>`;
586
583
  }
587
584
  }
588
- /** Icône Heroicons dans un schéma (port de Icon) : décorative, sauf si une infobulle ou un `aria-label` (attributs supplémentaires) la décrit. */
585
+ /** Heroicon in a schema: decorative, unless a tooltip or an `aria-label` (extra attribute) describes it. */
589
586
  export class Icon extends Component {
590
587
  _icon;
591
588
  _color = null;
@@ -594,9 +591,9 @@ export class Icon extends Component {
594
591
  constructor(name) { super(); this._icon = name; }
595
592
  static make(name) { return configured(new Icon(name)); }
596
593
  icon(name) { this._icon = name; return this; }
597
- /** Couleur (`primary` par défaut). */
594
+ /** Color (`primary` by default). */
598
595
  color(color) { this._color = color; return this; }
599
- /** Taille (`xs` … `2xl`) ; `base` revient à la taille par défaut. */
596
+ /** Size (`xs` … `2xl`); `base` resets to the default size. */
600
597
  size(size) { this._size = size === 'base' ? null : size; return this; }
601
598
  tooltip(text) { this._tooltip = text; return this; }
602
599
  async toHtml() {
@@ -615,7 +612,7 @@ export class Icon extends Component {
615
612
  return `${html}<span ${new Attributes().merge({ 'aria-describedby': ariaDescribedBy ? e(ariaDescribedBy) : null, 'aria-label': label ? e(label) : null, 'aria-labelledby': ariaLabelledBy ? e(ariaLabelledBy) : null, role: 'img' }).class(['fi-sr-only']).toHtml()}></span>`;
616
613
  }
617
614
  }
618
- /** Image dans un schéma (port de Image). Seules une adresse du site (`/…`) ou une adresse http(s) sont affichées. */
615
+ /** Image in a schema. Only same-site (`/…`) or http(s) URLs are rendered. */
619
616
  export class Image extends Component {
620
617
  _url;
621
618
  _alt;
@@ -633,11 +630,11 @@ export class Image extends Component {
633
630
  const css = typeof value === 'number' ? `${value}px` : value.trim();
634
631
  return /^(\d+(\.\d+)?(px|rem|em|%|vh|vw)?|auto)$/.test(css) ? css : null;
635
632
  }
636
- /** Hauteur (`8rem` par défaut) ; un nombre est en pixels. */
633
+ /** Height (`8rem` by default); a number is in pixels. */
637
634
  imageHeight(height) { this._height = Image.dimension(height); return this; }
638
635
  imageWidth(width) { this._width = Image.dimension(width); return this; }
639
636
  imageSize(size) { return this.imageWidth(size).imageHeight(size); }
640
- /** Alignement (`start`, `center`, `end`). */
637
+ /** Alignment (`start`, `center`, `end`). */
641
638
  alignment(alignment) { this._alignment = alignment; return this; }
642
639
  alignStart() { return this.alignment('start'); }
643
640
  alignCenter() { return this.alignment('center'); }
@@ -655,7 +652,7 @@ export class Image extends Component {
655
652
  return `<img alt="${e(await evaluate(this._alt, ctx))}" src="${e(url)}"${tooltip ? ` x-tooltip="${tooltip}"` : ''} ${attributes.toHtml()} />`;
656
653
  }
657
654
  }
658
- /** Liste à puces (port de UnorderedList) : chaque élément est un composant ; une chaîne devient un `Text`. Deux colonnes à partir de `sm`. */
655
+ /** Bulleted list: each item is a component; a string becomes a `Text`. Two columns from `sm`. */
659
656
  export class UnorderedList extends Component {
660
657
  children;
661
658
  _columns = { sm: 2 };
@@ -665,7 +662,7 @@ export class UnorderedList extends Component {
665
662
  static normalize(items) { return items.map((item) => (item instanceof Component ? item : Text.make(item))); }
666
663
  schema(items) { this.children = UnorderedList.normalize(items); return this; }
667
664
  columns(columns) { this._columns = columns; return this; }
668
- /** Taille du texte (`xs`, `sm`, `md`, `lg`). */
665
+ /** Text size (`xs`, `sm`, `md`, `lg`). */
669
666
  size(size) { this._size = size; return this; }
670
667
  getChildSchemas() { return [childSchema(this, this.children)]; }
671
668
  async toHtml() {
@@ -677,7 +674,7 @@ export class UnorderedList extends Component {
677
674
  return `<ul ${attributes.toHtml()}>${items.join('')}</ul>`;
678
675
  }
679
676
  }
680
- /** État vide (port de EmptyState) : icône, titre, description et un pied (actions, composants). */
677
+ /** Empty state: icon, heading, description and a footer (actions, components). */
681
678
  export class EmptyState extends Component {
682
679
  _heading;
683
680
  _description = null;
@@ -693,18 +690,18 @@ export class EmptyState extends Component {
693
690
  heading(heading) { this._heading = heading; return this; }
694
691
  description(description) { this._description = description; return this; }
695
692
  icon(name) { this._icon = name; return this; }
696
- /** Couleur de l'icône (`primary` par défaut). */
693
+ /** Icon color (`primary` by default). */
697
694
  iconColor(color) { this._iconColor = color; return this; }
698
695
  iconSize(size) { this._iconSize = size; return this; }
699
- /** Version resserrée. */
696
+ /** Compact variant. */
700
697
  compact(condition = true) { this._compact = condition; return this; }
701
- /** `false` : sans carte autour. */
698
+ /** `false`: no surrounding card. */
702
699
  contained(condition = true) { this._contained = condition; return this; }
703
- /** Balise du titre (`h2` par défaut). */
700
+ /** Heading tag (`h2` by default). */
704
701
  headingTag(tag) { this._headingTag = tag; return this; }
705
- /** Pied : actions et composants, en ligne. */
702
+ /** Footer: inline actions and components. */
706
703
  footer(items) { this._footer = items; return this; }
707
- /** Actions du pied, montées sur le schéma racine. */
704
+ /** Footer actions, mounted on the root schema. */
708
705
  getActions() { return actionsOf(this._footer); }
709
706
  async toHtml() {
710
707
  const ctx = this.context();
@@ -717,8 +714,8 @@ export class EmptyState extends Component {
717
714
  }
718
715
  const CALLOUT_ICONS = { danger: 'o-x-circle', info: 'o-information-circle', success: 'o-check-circle', warning: 'o-exclamation-circle' };
719
716
  /**
720
- * Encadré d'information (port de Callout) : statut (`info()`, `success()`, `warning()`, `danger()`) qui fixe couleur et icône,
721
- * titre, description, actions de pied (en liens) et actions de contrôle (à droite).
717
+ * Information box: a status (`info()`, `success()`, `warning()`, `danger()`) setting color and icon,
718
+ * heading, description, footer actions (as links) and control actions (on the right).
722
719
  */
723
720
  export class Callout extends Component {
724
721
  _heading;
@@ -737,30 +734,30 @@ export class Callout extends Component {
737
734
  static make(heading = null) { return configured(new Callout(heading)); }
738
735
  heading(heading) { this._heading = heading; return this; }
739
736
  description(description) { this._description = description; return this; }
740
- /** Statut : couleur, icône et préfixe lu par les lecteurs d'écran (« Note: »…). */
737
+ /** Status: sets color, icon and a screen-reader prefix ("Note:"…). */
741
738
  status(status) { this._status = status; return this; }
742
739
  danger() { return this.status('danger'); }
743
740
  info() { return this.status('info'); }
744
741
  success() { return this.status('success'); }
745
742
  warning() { return this.status('warning'); }
746
- /** Couleur du fond ; `null` retire celle du statut (l'icône la garde). */
743
+ /** Background color; `null` removes the status color (the icon keeps it). */
747
744
  color(color) { this._color = color; this._hasColor = true; return this; }
748
745
  icon(name) { this._icon = name; return this; }
749
746
  iconColor(color) { this._iconColor = color; return this; }
750
- /** Taille de l'icône (`lg` par défaut). */
747
+ /** Icon size (`lg` by default). */
751
748
  iconSize(size) { this._iconSize = size; return this; }
752
- /** Actions du pied, rendues en liens (port de `actions()` / `footerActions()`). */
749
+ /** Footer actions, rendered as links. */
753
750
  actions(actions) { this._footerActions = [...this._footerActions, ...actions]; return this; }
754
751
  footerActions(actions) { return this.actions(actions); }
755
- /** Alignement des actions du pied (`start`, `center`, `end`, `between`). */
752
+ /** Footer actions alignment (`start`, `center`, `end`, `between`). */
756
753
  footerActionsAlignment(alignment) { this._footerActionsAlignment = alignment; return this; }
757
- /** Pied libre (composants et actions), à la place des actions de pied. */
754
+ /** Free-form footer (components and actions), replacing the footer actions. */
758
755
  footer(items) { this._footer = items; return this; }
759
- /** Actions à droite de l'encadré (fermeture…), en petite taille. */
756
+ /** Small actions on the right of the callout (dismiss…). */
760
757
  controlActions(actions) { this._controlActions = [...this._controlActions, ...actions]; return this; }
761
758
  getColor() { return this._hasColor ? this._color : (this._color ?? this._status); }
762
759
  getIcon() { return this._icon ?? (this._status ? (CALLOUT_ICONS[this._status] ?? null) : null); }
763
- /** Actions de l'encadré, montées sur le schéma racine. */
760
+ /** Callout actions, mounted on the root schema. */
764
761
  getActions() { return [...(this._footer ? actionsOf(this._footer) : this._footerActions), ...this._controlActions]; }
765
762
  async toHtml() {
766
763
  const ctx = this.context();
@@ -783,8 +780,8 @@ export class Callout extends Component {
783
780
  }
784
781
  }
785
782
  /**
786
- * Champs accolés sous un seul libellé (port de FusedGroup) : chaque champ n'a plus qu'un libellé pour lecteurs d'écran,
787
- * et la première erreur de validation des champs s'affiche sous le groupe.
783
+ * Fields joined under a single label: each field keeps only a screen-reader label,
784
+ * and the first validation error among the fields is shown under the group.
788
785
  */
789
786
  export class FusedGroup extends Component {
790
787
  children;
@@ -798,10 +795,10 @@ export class FusedGroup extends Component {
798
795
  columns(columns) { this._columns = columns; return this; }
799
796
  label(label) { this._label = label; return this; }
800
797
  hiddenLabel(condition = true) { this._hiddenLabel = condition; return this; }
801
- /** Astérisque après le libellé (la validation reste celle de chaque champ). */
798
+ /** Asterisk after the label (validation stays per field). */
802
799
  markAsRequired(condition = true) { this._markedAsRequired = condition; return this; }
803
800
  getChildSchemas() { return [childSchema(this, this.children).columns(this._columns).gap(false).fieldWrapperView('filament-forms::plain-field-wrapper')]; }
804
- /** Première erreur des champs du groupe (y compris d'un élément d'un champ à valeurs multiples). */
801
+ /** First error among the group's fields (including one on an item of a multi-valued field). */
805
802
  firstError() {
806
803
  const errors = this.livewire._errors ?? {};
807
804
  for (const component of this.getChildSchemas()[0].getComponents()) {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@navette-js/schemas",
3
- "version": "1.0.0-beta.1",
4
- "description": "Layout components and schemas for Navette, the Node.js port of Filament.",
3
+ "version": "1.0.0-beta.2",
4
+ "description": "Layout components and schemas for Navette admin panels.",
5
5
  "license": "MIT",
6
6
  "type": "module",
7
7
  "exports": {
@@ -31,7 +31,6 @@
31
31
  },
32
32
  "keywords": [
33
33
  "navette",
34
- "filament",
35
34
  "admin",
36
35
  "panel",
37
36
  "livewire",
@@ -39,7 +38,7 @@
39
38
  "node"
40
39
  ],
41
40
  "dependencies": {
42
- "@navette-js/support": "1.0.0-beta.1"
41
+ "@navette-js/support": "1.0.0-beta.2"
43
42
  },
44
43
  "publishConfig": {
45
44
  "access": "public",
@@ -1,2 +1,2 @@
1
- <%# Enveloppe de colonne d'un composant de schéma — port de Filament\Schemas\Components\Component::toSchemaHtml() %>
1
+ <%# Grid column wrapper of a schema component. %>
2
2
  <div<% if (key !== null) { %> wire:partial="schema-component::<%- key %>"<% } %><% if (isVisible) { %> x-data="<%- alpine %>"<% } %> <%- attributes %>><% if (isVisible) { %><div class="fi-sc-component"><%- html %></div><% } %></div>