@navette-js/schemas 1.0.0-beta.1 → 1.0.0-beta.3
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 +2 -2
- package/lib/index.d.ts +91 -93
- package/lib/index.js +103 -106
- package/package.json +3 -4
- package/views/component.ejs +1 -1
package/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# @navette-js/schemas
|
|
2
2
|
|
|
3
|
-
Layout components and schemas for Navette
|
|
3
|
+
Layout components and schemas for Navette admin panels.
|
|
4
4
|
|
|
5
|
-
Part of [Navette](https://github.com/NavetteJS/navette),
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
36
|
+
/** Hidden for the given operation(s) (`'create'`, `'edit'`…). */
|
|
37
37
|
hiddenOn(operations: string | string[]): this;
|
|
38
|
-
/** Visible
|
|
38
|
+
/** Visible only for the given operation(s). */
|
|
39
39
|
visibleOn(operations: string | string[]): this;
|
|
40
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
47
|
+
/** Server methods the component's JavaScript may call (announced to the browser). */
|
|
48
48
|
getExposedMethods(): string[];
|
|
49
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
59
|
+
/** The component's own HTML, without its grid wrapper. */
|
|
60
60
|
abstract toHtml(): Promise<string>;
|
|
61
|
-
/**
|
|
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
|
-
/**
|
|
88
|
+
/** Class placed before the grid classes (e.g. `fi-section-content`). */
|
|
89
89
|
extraClass(name: string | null): this;
|
|
90
|
-
/**
|
|
90
|
+
/** Tighter spacing between components (`fi-sc-dense`). */
|
|
91
91
|
dense(condition?: boolean): this;
|
|
92
|
-
/**
|
|
92
|
+
/** Partially rendered schema: its root carries `wire:partial="schema.<key>"`. */
|
|
93
93
|
partiallyRendered(condition?: boolean): this;
|
|
94
94
|
private _partialName;
|
|
95
|
-
/**
|
|
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
|
|
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
|
-
*
|
|
103
|
-
* (
|
|
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
|
-
/**
|
|
114
|
+
/** All components, depth-first. */
|
|
115
115
|
getFlatComponents(): Component[];
|
|
116
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
*
|
|
150
|
-
*
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
174
|
+
/** Collapsible by clicking its header; `collapsed()` starts it collapsed. */
|
|
176
175
|
collapsible(condition?: boolean): this;
|
|
177
176
|
collapsed(condition?: boolean): this;
|
|
178
|
-
/** Actions
|
|
177
|
+
/** Actions shown to the right of the heading. */
|
|
179
178
|
afterHeader(actions: Renderable[]): this;
|
|
180
|
-
/** Actions
|
|
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
|
-
*
|
|
187
|
-
*
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
272
|
+
/** Item in an inline row: a schema component or an action. */
|
|
275
273
|
export type InlineItem = Component | Renderable;
|
|
276
274
|
/**
|
|
277
|
-
*
|
|
278
|
-
*
|
|
279
|
-
* `actionView
|
|
280
|
-
* `scope`
|
|
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
|
-
*
|
|
290
|
-
*
|
|
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
|
-
/**
|
|
302
|
+
/** Keeps the legend for screen readers only. */
|
|
305
303
|
hiddenLabel(condition?: boolean): this;
|
|
306
|
-
/** `false
|
|
304
|
+
/** `false`: no border or padding. */
|
|
307
305
|
contained(condition?: boolean): this;
|
|
308
|
-
/**
|
|
306
|
+
/** Asterisk after the legend (the fieldset itself is never validated). */
|
|
309
307
|
markAsRequired(condition?: boolean): this;
|
|
310
|
-
/**
|
|
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
|
-
*
|
|
318
|
-
*
|
|
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
|
-
/**
|
|
336
|
+
/** Renders as a badge. */
|
|
339
337
|
badge(condition?: Lazy<boolean, ComponentContext>): this;
|
|
340
|
-
/**
|
|
338
|
+
/** Color (`gray` by default; `primary`, `danger`…). */
|
|
341
339
|
color(color: Lazy<string | null, ComponentContext>): this;
|
|
342
|
-
/**
|
|
340
|
+
/** Text or badge size (`xs`, `sm`, `md`, `lg`). */
|
|
343
341
|
size(size: string | null): this;
|
|
344
|
-
/**
|
|
342
|
+
/** Font weight (`bold`, `semibold`, `medium`…). */
|
|
345
343
|
weight(weight: string | null): this;
|
|
346
|
-
/**
|
|
344
|
+
/** Font family (`sans`, `serif`, `mono`). */
|
|
347
345
|
fontFamily(family: string | null): this;
|
|
348
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
368
|
+
/** Color (`primary` by default). */
|
|
371
369
|
color(color: Lazy<string | null, ComponentContext>): this;
|
|
372
|
-
/**
|
|
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
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
431
|
+
/** Icon color (`primary` by default). */
|
|
434
432
|
iconColor(color: string | null): this;
|
|
435
433
|
iconSize(size: string | null): this;
|
|
436
|
-
/**
|
|
434
|
+
/** Compact variant. */
|
|
437
435
|
compact(condition?: boolean): this;
|
|
438
|
-
/** `false
|
|
436
|
+
/** `false`: no surrounding card. */
|
|
439
437
|
contained(condition?: boolean): this;
|
|
440
|
-
/**
|
|
438
|
+
/** Heading tag (`h2` by default). */
|
|
441
439
|
headingTag(tag: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6'): this;
|
|
442
|
-
/**
|
|
440
|
+
/** Footer: inline actions and components. */
|
|
443
441
|
footer(items: InlineItem[]): this;
|
|
444
|
-
/**
|
|
442
|
+
/** Footer actions, mounted on the root schema. */
|
|
445
443
|
getActions(): Renderable[];
|
|
446
444
|
toHtml(): Promise<string>;
|
|
447
445
|
}
|
|
448
446
|
/**
|
|
449
|
-
*
|
|
450
|
-
*
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
477
|
+
/** Icon size (`lg` by default). */
|
|
480
478
|
iconSize(size: string | null): this;
|
|
481
|
-
/**
|
|
479
|
+
/** Footer actions, rendered as links. */
|
|
482
480
|
actions(actions: Renderable[]): this;
|
|
483
481
|
footerActions(actions: Renderable[]): this;
|
|
484
|
-
/**
|
|
482
|
+
/** Footer actions alignment (`start`, `center`, `end`, `between`). */
|
|
485
483
|
footerActionsAlignment(alignment: string): this;
|
|
486
|
-
/**
|
|
484
|
+
/** Free-form footer (components and actions), replacing the footer actions. */
|
|
487
485
|
footer(items: InlineItem[] | null): this;
|
|
488
|
-
/**
|
|
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
|
-
/**
|
|
490
|
+
/** Callout actions, mounted on the root schema. */
|
|
493
491
|
getActions(): Renderable[];
|
|
494
492
|
toHtml(): Promise<string>;
|
|
495
493
|
}
|
|
496
494
|
/**
|
|
497
|
-
*
|
|
498
|
-
*
|
|
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
|
-
/**
|
|
510
|
+
/** Asterisk after the label (validation stays per field). */
|
|
513
511
|
markAsRequired(condition?: boolean): this;
|
|
514
512
|
getChildSchemas(): Schema[];
|
|
515
|
-
/**
|
|
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 —
|
|
2
|
-
//
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
33
|
+
/** Starting grid column, from the `lg` breakpoint. */
|
|
34
34
|
columnStart(start) { this._columnStart = start; return this; }
|
|
35
|
-
/**
|
|
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
|
-
/**
|
|
40
|
+
/** Server methods the component's JavaScript may call (announced to the browser). */
|
|
41
41
|
getExposedMethods() { return []; }
|
|
42
|
-
/**
|
|
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
|
-
/**
|
|
45
|
+
/** Absolute component key: `<schema key>.<key or name>`, or null. */
|
|
46
46
|
getKey() {
|
|
47
|
-
// `::data::`
|
|
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
|
-
//
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
110
|
+
/** Class placed before the grid classes (e.g. `fi-section-content`). */
|
|
111
111
|
extraClass(name) { this._extraClass = name; return this; }
|
|
112
|
-
/**
|
|
112
|
+
/** Tighter spacing between components (`fi-sc-dense`). */
|
|
113
113
|
dense(condition = true) { this._dense = condition; return this; }
|
|
114
|
-
/**
|
|
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
|
-
/**
|
|
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
|
|
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
|
-
*
|
|
125
|
-
* (
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
*
|
|
211
|
-
*
|
|
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
|
-
/**
|
|
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
|
-
//
|
|
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
|
-
/**
|
|
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
|
|
253
|
+
/** Actions shown to the right of the heading. */
|
|
255
254
|
afterHeader(actions) { this._afterHeader = actions; return this; }
|
|
256
|
-
/** Actions
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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 && '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
|
-
*
|
|
285
|
-
*
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
//
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
*
|
|
430
|
-
*
|
|
431
|
-
* `actionView
|
|
432
|
-
* `scope`
|
|
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
|
-
//
|
|
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
|
|
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
|
-
/**
|
|
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
|
-
*
|
|
483
|
-
*
|
|
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
|
-
/**
|
|
494
|
+
/** Keeps the legend for screen readers only. */
|
|
498
495
|
hiddenLabel(condition = true) { this._hiddenLabel = condition; return this; }
|
|
499
|
-
/** `false
|
|
496
|
+
/** `false`: no border or padding. */
|
|
500
497
|
contained(condition = true) { this._contained = condition; return this; }
|
|
501
|
-
/**
|
|
498
|
+
/** Asterisk after the legend (the fieldset itself is never validated). */
|
|
502
499
|
markAsRequired(condition = true) { this._markedAsRequired = condition; return this; }
|
|
503
|
-
/**
|
|
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
|
-
*
|
|
522
|
-
*
|
|
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
|
-
/**
|
|
539
|
+
/** Renders as a badge. */
|
|
543
540
|
badge(condition = true) { this._badge = condition; return this; }
|
|
544
|
-
/**
|
|
541
|
+
/** Color (`gray` by default; `primary`, `danger`…). */
|
|
545
542
|
color(color) { this._color = color; return this; }
|
|
546
|
-
/**
|
|
543
|
+
/** Text or badge size (`xs`, `sm`, `md`, `lg`). */
|
|
547
544
|
size(size) { this._size = size; return this; }
|
|
548
|
-
/**
|
|
545
|
+
/** Font weight (`bold`, `semibold`, `medium`…). */
|
|
549
546
|
weight(weight) { this._weight = weight; return this; }
|
|
550
|
-
/**
|
|
547
|
+
/** Font family (`sans`, `serif`, `mono`). */
|
|
551
548
|
fontFamily(family) { this._fontFamily = family; return this; }
|
|
552
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
//
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
594
|
+
/** Color (`primary` by default). */
|
|
598
595
|
color(color) { this._color = color; return this; }
|
|
599
|
-
/**
|
|
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
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
696
|
+
/** Compact variant. */
|
|
700
697
|
compact(condition = true) { this._compact = condition; return this; }
|
|
701
|
-
/** `false
|
|
698
|
+
/** `false`: no surrounding card. */
|
|
702
699
|
contained(condition = true) { this._contained = condition; return this; }
|
|
703
|
-
/**
|
|
700
|
+
/** Heading tag (`h2` by default). */
|
|
704
701
|
headingTag(tag) { this._headingTag = tag; return this; }
|
|
705
|
-
/**
|
|
702
|
+
/** Footer: inline actions and components. */
|
|
706
703
|
footer(items) { this._footer = items; return this; }
|
|
707
|
-
/**
|
|
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
|
-
*
|
|
721
|
-
*
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
747
|
+
/** Icon size (`lg` by default). */
|
|
751
748
|
iconSize(size) { this._iconSize = size; return this; }
|
|
752
|
-
/**
|
|
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
|
-
/**
|
|
752
|
+
/** Footer actions alignment (`start`, `center`, `end`, `between`). */
|
|
756
753
|
footerActionsAlignment(alignment) { this._footerActionsAlignment = alignment; return this; }
|
|
757
|
-
/**
|
|
754
|
+
/** Free-form footer (components and actions), replacing the footer actions. */
|
|
758
755
|
footer(items) { this._footer = items; return this; }
|
|
759
|
-
/**
|
|
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
|
-
/**
|
|
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
|
-
*
|
|
787
|
-
*
|
|
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
|
-
/**
|
|
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
|
-
/**
|
|
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.
|
|
4
|
-
"description": "Layout components and schemas for Navette
|
|
3
|
+
"version": "1.0.0-beta.3",
|
|
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.
|
|
41
|
+
"@navette-js/support": "1.0.0-beta.3"
|
|
43
42
|
},
|
|
44
43
|
"publishConfig": {
|
|
45
44
|
"access": "public",
|
package/views/component.ejs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
<%#
|
|
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>
|