@cadriciel/ui 0.9.0 → 0.9.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/fesm2022/cadriciel-ui.mjs +949 -413
- package/fesm2022/cadriciel-ui.mjs.map +1 -1
- package/package.json +1 -1
- package/types/cadriciel-ui.d.ts +417 -42
|
@@ -2136,14 +2136,28 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImpo
|
|
|
2136
2136
|
* <cad-radio value="session" label="Session" [disabled]="true" />
|
|
2137
2137
|
* </cad-radio-group>
|
|
2138
2138
|
* CVA<T> sur le GROUPE. Clavier : ←/→/↑/↓ déplacent la sélection (pattern WAI-ARIA radiogroup).
|
|
2139
|
-
* @atelier icone=circle-dot largeur=2
|
|
2139
|
+
* @atelier icone=circle-dot largeur=2 conteneur=direct hauteur=4
|
|
2140
2140
|
*/
|
|
2141
2141
|
class CadRadioGroupComponent extends CadValueAccessor {
|
|
2142
2142
|
orientation = input('vertical', ...(ngDevMode ? [{ debugName: "orientation" }] : /* istanbul ignore next */ []));
|
|
2143
2143
|
ariaLabel = input('', ...(ngDevMode ? [{ debugName: "ariaLabel" }] : /* istanbul ignore next */ []));
|
|
2144
2144
|
name = input(cadId('cad-radio'), ...(ngDevMode ? [{ debugName: "name" }] : /* istanbul ignore next */ []));
|
|
2145
2145
|
changed = output();
|
|
2146
|
-
|
|
2146
|
+
radiosProjetes = contentChildren(forwardRef(() => CadRadioComponent), { ...(ngDevMode ? { debugName: "radiosProjetes" } : /* istanbul ignore next */ {}), descendants: true });
|
|
2147
|
+
/** Radios POSÉS hors gabarit, annoncés par `enregistrerEnfants`. */
|
|
2148
|
+
radiosPoses = signal([], ...(ngDevMode ? [{ debugName: "radiosPoses" }] : /* istanbul ignore next */ []));
|
|
2149
|
+
radios = computed(() => [...this.radiosProjetes(), ...this.radiosPoses()], ...(ngDevMode ? [{ debugName: "radios" }] : /* istanbul ignore next */ []));
|
|
2150
|
+
/** Reçoit la LISTE COMPLÈTE des radios posés, et se RATTACHE à chacun. */
|
|
2151
|
+
enregistrerEnfants(instances) {
|
|
2152
|
+
const pieces = instances.filter((i) => i instanceof CadRadioComponent);
|
|
2153
|
+
// Le générique du groupe et celui du radio sont indépendants au montage ; la
|
|
2154
|
+
// relation est structurelle, pas typée. On la pose explicitement plutôt que de
|
|
2155
|
+
// faire remonter un paramètre de type jusqu'au poseur, qui ne connaît ni l'un ni
|
|
2156
|
+
// l'autre.
|
|
2157
|
+
for (const p of pieces)
|
|
2158
|
+
p.rattacher(this);
|
|
2159
|
+
this.radiosPoses.set(pieces);
|
|
2160
|
+
}
|
|
2147
2161
|
select(v) { if (this.isDisabled())
|
|
2148
2162
|
return; this.commit(v); this.changed.emit(v); this.markTouched(); }
|
|
2149
2163
|
onKey(e) {
|
|
@@ -2161,32 +2175,69 @@ class CadRadioGroupComponent extends CadValueAccessor {
|
|
|
2161
2175
|
next.focus();
|
|
2162
2176
|
}
|
|
2163
2177
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: CadRadioGroupComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
2164
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.20", type: CadRadioGroupComponent, isStandalone: true, selector: "cad-radio-group", inputs: { orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { changed: "changed" }, host: { attributes: { "role": "radiogroup" }, listeners: { "keydown": "onKey($event)" }, properties: { "class.is-horizontal": "orientation()===\"horizontal\"", "class.is-disabled": "isDisabled()", "attr.aria-label": "ariaLabel() || null" }, classAttribute: "cad-radio-group" }, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => CadRadioGroupComponent), multi: true }], queries: [{ propertyName: "
|
|
2178
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.20", type: CadRadioGroupComponent, isStandalone: true, selector: "cad-radio-group", inputs: { orientation: { classPropertyName: "orientation", publicName: "orientation", isSignal: true, isRequired: false, transformFunction: null }, ariaLabel: { classPropertyName: "ariaLabel", publicName: "ariaLabel", isSignal: true, isRequired: false, transformFunction: null }, name: { classPropertyName: "name", publicName: "name", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { changed: "changed" }, host: { attributes: { "role": "radiogroup" }, listeners: { "keydown": "onKey($event)" }, properties: { "class.is-horizontal": "orientation()===\"horizontal\"", "class.is-disabled": "isDisabled()", "attr.aria-label": "ariaLabel() || null" }, classAttribute: "cad-radio-group" }, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => CadRadioGroupComponent), multi: true }], queries: [{ propertyName: "radiosProjetes", predicate: i0.forwardRef(() => CadRadioComponent), descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: `<ng-content />`, isInline: true, styles: [":host{display:inline-flex;flex-direction:column;gap:8px}:host(.is-horizontal){flex-direction:row;flex-wrap:wrap;gap:16px}:host(.is-disabled){opacity:.55}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
2165
2179
|
}
|
|
2166
2180
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: CadRadioGroupComponent, decorators: [{
|
|
2167
2181
|
type: Component,
|
|
2168
2182
|
args: [{ selector: 'cad-radio-group', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => CadRadioGroupComponent), multi: true }], host: { class: 'cad-radio-group', role: 'radiogroup', '[class.is-horizontal]': 'orientation()==="horizontal"', '[class.is-disabled]': 'isDisabled()', '[attr.aria-label]': 'ariaLabel() || null', '(keydown)': 'onKey($event)' }, template: `<ng-content />`, styles: [":host{display:inline-flex;flex-direction:column;gap:8px}:host(.is-horizontal){flex-direction:row;flex-wrap:wrap;gap:16px}:host(.is-disabled){opacity:.55}\n"] }]
|
|
2169
|
-
}], propDecorators: { orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], changed: [{ type: i0.Output, args: ["changed"] }],
|
|
2183
|
+
}], propDecorators: { orientation: [{ type: i0.Input, args: [{ isSignal: true, alias: "orientation", required: false }] }], ariaLabel: [{ type: i0.Input, args: [{ isSignal: true, alias: "ariaLabel", required: false }] }], name: [{ type: i0.Input, args: [{ isSignal: true, alias: "name", required: false }] }], changed: [{ type: i0.Output, args: ["changed"] }], radiosProjetes: [{ type: i0.ContentChildren, args: [forwardRef(() => CadRadioComponent), { ...{ descendants: true }, isSignal: true }] }] } });
|
|
2184
|
+
/**
|
|
2185
|
+
* Un choix du groupe : `<cad-radio [value]="'a'" label="Option A">`.
|
|
2186
|
+
* @atelier icone=circle-dot conteneur=flux dans=cad-radio-group pose-label=Option
|
|
2187
|
+
*/
|
|
2170
2188
|
class CadRadioComponent {
|
|
2171
|
-
|
|
2172
|
-
|
|
2189
|
+
/**
|
|
2190
|
+
* Le groupe d'accueil — INJECTÉ dans un gabarit, POUSSÉ par l'hôte à la pose.
|
|
2191
|
+
*
|
|
2192
|
+
* ⚠️ OPTIONNEL depuis le 27/08, même correctif que `cad-accordion-panel` : l'injection
|
|
2193
|
+
* obligatoire levait `NG0201` dès qu'on créait le bouton à la main, et `gen-catalog`
|
|
2194
|
+
* classait `cad-radio` « contextuel » — il n'était pas posable. `cad-tab`, la pièce
|
|
2195
|
+
* jumelle des onglets, n'injecte rien : elle est PASSIVE et son hôte la pilote. La
|
|
2196
|
+
* divergence était d'écriture, pas de nature (SZU 27/08).
|
|
2197
|
+
*/
|
|
2198
|
+
groupInjecte = inject(forwardRef(() => CadRadioGroupComponent), { optional: true });
|
|
2199
|
+
groupPose = signal(null, ...(ngDevMode ? [{ debugName: "groupPose" }] : /* istanbul ignore next */ []));
|
|
2200
|
+
group = computed(() => this.groupInjecte ?? this.groupPose(), ...(ngDevMode ? [{ debugName: "group" }] : /* istanbul ignore next */ []));
|
|
2201
|
+
/** Le groupe s'annonce au bouton qu'il accueille. Cf. `atelier/atelier.pieces.ts`. */
|
|
2202
|
+
rattacher(g) {
|
|
2203
|
+
this.groupPose.set(g);
|
|
2204
|
+
}
|
|
2205
|
+
/** Sélectionne, si un groupe existe. Un radio solitaire ne prétend pas gérer un choix. */
|
|
2206
|
+
choisir() {
|
|
2207
|
+
this.group()?.select(this.value());
|
|
2208
|
+
}
|
|
2209
|
+
/**
|
|
2210
|
+
* La valeur que ce choix représente.
|
|
2211
|
+
*
|
|
2212
|
+
* DÉFAUT UNIQUE plutôt que `input.required` (27/08) — même précédent que
|
|
2213
|
+
* `cad-accordion-panel`, qui se donne `cadId('cad-panel')`. Une entrée requise LÈVE
|
|
2214
|
+
* dès qu'on instancie le composant sans la fournir : posé dans l'atelier, le radio
|
|
2215
|
+
* mourait à la construction et le poseur l'écartait EN SILENCE (groupe vide, aucune
|
|
2216
|
+
* erreur visible). Un défaut unique par instance rend un radio posé immédiatement
|
|
2217
|
+
* cohérent — deux radios ne se retrouvent jamais cochés ensemble — et n'enlève rien à
|
|
2218
|
+
* l'usage écrit, où l'on passe toujours une valeur.
|
|
2219
|
+
*/
|
|
2220
|
+
value = input(cadId('cad-radio-v'), ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
2173
2221
|
label = input('', ...(ngDevMode ? [{ debugName: "label" }] : /* istanbul ignore next */ []));
|
|
2174
2222
|
hint = input('', ...(ngDevMode ? [{ debugName: "hint" }] : /* istanbul ignore next */ []));
|
|
2175
2223
|
disabled = input(false, { ...(ngDevMode ? { debugName: "disabled" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
2176
2224
|
id = cadId('cad-radio');
|
|
2177
|
-
checked = computed(() => this.group
|
|
2225
|
+
checked = computed(() => this.group()?.value() === this.value(), ...(ngDevMode ? [{ debugName: "checked" }] : /* istanbul ignore next */ []));
|
|
2178
2226
|
/** Roving tabindex : seul l'élément coché (ou le 1er) est tabulable. */
|
|
2179
2227
|
tabIndex = computed(() => {
|
|
2180
2228
|
if (this.checked())
|
|
2181
2229
|
return 0;
|
|
2182
|
-
const
|
|
2183
|
-
|
|
2230
|
+
const g = this.group();
|
|
2231
|
+
if (!g)
|
|
2232
|
+
return 0;
|
|
2233
|
+
const first = g.radios().find(r => !r.disabled());
|
|
2234
|
+
return g.value() == null && first === this ? 0 : -1;
|
|
2184
2235
|
}, ...(ngDevMode ? [{ debugName: "tabIndex" }] : /* istanbul ignore next */ []));
|
|
2185
2236
|
focus() { document.getElementById(this.id)?.focus(); }
|
|
2186
2237
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: CadRadioComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
2187
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: CadRadioComponent, isStandalone: true, selector: "cad-radio", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired:
|
|
2188
|
-
<button type="button" role="radio" [id]="id" [attr.aria-checked]="checked()" [tabindex]="tabIndex()" [disabled]="disabled() || group
|
|
2189
|
-
[attr.aria-labelledby]="label() ? id + '-l' : null" (click)="
|
|
2238
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: CadRadioComponent, isStandalone: true, selector: "cad-radio", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null } }, host: { properties: { "class.is-on": "checked()", "class.is-disabled": "disabled() || !!group()?.isDisabled()" }, classAttribute: "cad-radio" }, ngImport: i0, template: `
|
|
2239
|
+
<button type="button" role="radio" [id]="id" [attr.aria-checked]="checked()" [tabindex]="tabIndex()" [disabled]="disabled() || !!group()?.isDisabled()"
|
|
2240
|
+
[attr.aria-labelledby]="label() ? id + '-l' : null" (click)="choisir()">
|
|
2190
2241
|
<span class="cad-radio__dot"></span>
|
|
2191
2242
|
</button>
|
|
2192
2243
|
@if (label()) {<label [id]="id + '-l'" [attr.for]="id" class="cad-radio__label">{{ label() }}@if (hint()) {<small>{{ hint() }}</small>}</label>}
|
|
@@ -2195,15 +2246,15 @@ class CadRadioComponent {
|
|
|
2195
2246
|
}
|
|
2196
2247
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: CadRadioComponent, decorators: [{
|
|
2197
2248
|
type: Component,
|
|
2198
|
-
args: [{ selector: 'cad-radio', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'cad-radio', '[class.is-on]': 'checked()', '[class.is-disabled]': 'disabled() || group
|
|
2199
|
-
<button type="button" role="radio" [id]="id" [attr.aria-checked]="checked()" [tabindex]="tabIndex()" [disabled]="disabled() || group
|
|
2200
|
-
[attr.aria-labelledby]="label() ? id + '-l' : null" (click)="
|
|
2249
|
+
args: [{ selector: 'cad-radio', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'cad-radio', '[class.is-on]': 'checked()', '[class.is-disabled]': 'disabled() || !!group()?.isDisabled()' }, template: `
|
|
2250
|
+
<button type="button" role="radio" [id]="id" [attr.aria-checked]="checked()" [tabindex]="tabIndex()" [disabled]="disabled() || !!group()?.isDisabled()"
|
|
2251
|
+
[attr.aria-labelledby]="label() ? id + '-l' : null" (click)="choisir()">
|
|
2201
2252
|
<span class="cad-radio__dot"></span>
|
|
2202
2253
|
</button>
|
|
2203
2254
|
@if (label()) {<label [id]="id + '-l'" [attr.for]="id" class="cad-radio__label">{{ label() }}@if (hint()) {<small>{{ hint() }}</small>}</label>}
|
|
2204
2255
|
<ng-content />
|
|
2205
2256
|
`, styles: [":host{display:inline-flex;align-items:flex-start;gap:8px;font-family:var(--cad-font);font-size:var(--cad-font-size);color:var(--cad-fg)}button{all:unset;display:inline-flex;cursor:pointer;border-radius:50%;margin-top:1px}:host-context(.cad-touch) button{min-width:44px;min-height:44px;justify-content:center;align-items:center;margin:-12px;padding:12px;box-sizing:border-box}button:focus-visible{outline:2px solid var(--cad-ring);outline-offset:2px}button[disabled]{cursor:not-allowed}:host(.is-disabled){opacity:.55}.cad-radio__dot{width:16px;height:16px;box-sizing:border-box;border:1.5px solid var(--cad-border-strong);border-radius:50%;background:var(--cad-input-bg);display:grid;place-items:center;transition:all var(--cad-dur)}.cad-radio__dot:after{content:\"\";width:6px;height:6px;border-radius:50%;background:var(--cad-fg-on-accent);transform:scale(0);transition:transform var(--cad-dur)}:host(.is-on) .cad-radio__dot{background:var(--cad-accent);border-color:var(--cad-accent)}:host(.is-on) .cad-radio__dot:after{transform:scale(1)}:host(:hover:not(.is-disabled)) .cad-radio__dot{border-color:var(--cad-accent)}.cad-radio__label{cursor:pointer;-webkit-user-select:none;user-select:none;display:grid}.cad-radio__label small{color:var(--cad-fg-muted);font-size:11.5px}\n"] }]
|
|
2206
|
-
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required:
|
|
2257
|
+
}], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }] } });
|
|
2207
2258
|
|
|
2208
2259
|
/**
|
|
2209
2260
|
* <cad-segmented [(value)]="view" [options]="[{label:'Tableau',value:'t'},{label:'SQL',value:'s',icon:'code'}]" />
|
|
@@ -6105,7 +6156,15 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImpo
|
|
|
6105
6156
|
* Grille responsive : `<cad-grid cols="1 sm:2 lg:4" gap="md">` (breakpoints FENÊTRE, mobile-first)
|
|
6106
6157
|
* ou `<cad-grid min="220px">` (auto-fit : autant de colonnes que le CONTENEUR en accepte — préférer pour les composants).
|
|
6107
6158
|
* Enfant : `<div cadCol="2">` / `cadCol="1 md:2"` = span, `cadCol="full"` = toute la largeur.
|
|
6108
|
-
*
|
|
6159
|
+
*
|
|
6160
|
+
* CONTENEUR D'ATELIER en régime `direct`, et non `flux` (27/08) : en flux, l'atelier
|
|
6161
|
+
* envelopperait les enfants dans SA propre grille 12 colonnes, la grille posée n'aurait
|
|
6162
|
+
* plus qu'un seul enfant et son `cols` ne servirait plus à rien — un conteneur qui a
|
|
6163
|
+
* l'air de marcher et ne fait rien. En direct, les enfants sont projetés nus et c'est
|
|
6164
|
+
* bien `cols` / `min` qui les place, ce qu'on vient chercher en posant une grille.
|
|
6165
|
+
* Aucune trappe d'accueil n'est nécessaire ici : `cad-grid` ne fait ni requête de
|
|
6166
|
+
* contenu ni injection depuis ses enfants, il ne les REGARDE pas, il les dispose.
|
|
6167
|
+
* @atelier icone=grid conteneur=direct largeur=12 hauteur=4
|
|
6109
6168
|
*/
|
|
6110
6169
|
class CadGridComponent {
|
|
6111
6170
|
cols = input('1', ...(ngDevMode ? [{ debugName: "cols" }] : /* istanbul ignore next */ []));
|
|
@@ -6224,7 +6283,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImpo
|
|
|
6224
6283
|
}], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], padding: [{ type: i0.Input, args: [{ isSignal: true, alias: "padding", required: false }] }] } });
|
|
6225
6284
|
/**
|
|
6226
6285
|
* Espace flexible (pousse ce qui suit) ou fixe : `<cad-spacer/>` · `<cad-spacer size="lg"/>`
|
|
6227
|
-
*
|
|
6286
|
+
*
|
|
6287
|
+
* `surface=aucune` : il occupe sa place et ne dessine RIEN. Posé dans une maquette, il
|
|
6288
|
+
* fait donc exactement son travail en restant invisible — indistinguable d'un composant
|
|
6289
|
+
* qui n'aurait pas été posé (SZU 27/08). L'atelier s'en sert pour le MATÉRIALISER le
|
|
6290
|
+
* temps de la conception ; le rendu, lui, n'en sait rien.
|
|
6291
|
+
* @atelier icone=move-horizontal surface=aucune
|
|
6228
6292
|
*/
|
|
6229
6293
|
class CadSpacerComponent {
|
|
6230
6294
|
size = input('', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
@@ -6237,7 +6301,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImpo
|
|
|
6237
6301
|
args: [{ selector: 'cad-spacer', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'cad-spacer', '[style.flex]': 'size() ? "none" : "1 1 auto"', '[style.width]': 'size() ? cadGap(size()) : null', '[style.height]': 'size() ? cadGap(size()) : null' }, template: ``, styles: [":host{display:block}\n"] }]
|
|
6238
6302
|
}], propDecorators: { size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }] } });
|
|
6239
6303
|
|
|
6240
|
-
/**
|
|
6304
|
+
/**
|
|
6305
|
+
* Panneau d'un splitter : `<cad-splitter-panel [size]="30" [minSize]="10">…</cad-splitter-panel>` (size en %).
|
|
6306
|
+
* @atelier icone=square conteneur=flux dans=cad-splitter
|
|
6307
|
+
*/
|
|
6241
6308
|
class CadSplitterPanelComponent {
|
|
6242
6309
|
size = input(null, { ...(ngDevMode ? { debugName: "size" } : /* istanbul ignore next */ {}), transform: v => (v == null || v === '' ? null : Number(v)) });
|
|
6243
6310
|
minSize = input(0, { ...(ngDevMode ? { debugName: "minSize" } : /* istanbul ignore next */ {}), transform: numberAttribute });
|
|
@@ -6253,7 +6320,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImpo
|
|
|
6253
6320
|
* <cad-splitter-panel>…</cad-splitter-panel><cad-splitter-panel>…</cad-splitter-panel>
|
|
6254
6321
|
* </cad-splitter>
|
|
6255
6322
|
* Gouttière glissable (pointer), double-clic = tailles initiales, clavier ←→/↑↓ (±2 %), `role=separator`, persistance localStorage via `stateKey`, imbriquable.
|
|
6256
|
-
* @atelier icone=columns
|
|
6323
|
+
* @atelier icone=columns conteneur=direct largeur=12 hauteur=8
|
|
6257
6324
|
*/
|
|
6258
6325
|
class CadSplitterComponent {
|
|
6259
6326
|
host = inject(ElementRef);
|
|
@@ -6264,7 +6331,24 @@ class CadSplitterComponent {
|
|
|
6264
6331
|
stateKey = input('', ...(ngDevMode ? [{ debugName: "stateKey" }] : /* istanbul ignore next */ []));
|
|
6265
6332
|
resizeStart = output();
|
|
6266
6333
|
resizeEnd = output();
|
|
6267
|
-
|
|
6334
|
+
/** Panneaux déclarés dans un GABARIT — la voie normale. */
|
|
6335
|
+
panelsProjetes = contentChildren(CadSplitterPanelComponent, ...(ngDevMode ? [{ debugName: "panelsProjetes" }] : /* istanbul ignore next */ []));
|
|
6336
|
+
/**
|
|
6337
|
+
* Panneaux POSÉS, créés hors gabarit et annoncés par `enregistrerEnfants`
|
|
6338
|
+
* (cf. `atelier/atelier.pieces.ts`).
|
|
6339
|
+
*
|
|
6340
|
+
* Sans eux, `panels()` reste vide pour un splitter posé : aucune gouttière, aucune
|
|
6341
|
+
* taille calculée, `grid-template-columns` vide — mesuré à `gouttieres=0` le 27/08.
|
|
6342
|
+
* Les panneaux s'affichaient quand même (ils sont projetés), ce qui donnait un
|
|
6343
|
+
* splitter d'apparence correcte mais sans mise en page ni poignée.
|
|
6344
|
+
*/
|
|
6345
|
+
panelsPoses = signal([], ...(ngDevMode ? [{ debugName: "panelsPoses" }] : /* istanbul ignore next */ []));
|
|
6346
|
+
/** Tous les panneaux : projetés d'abord, posés ensuite — l'ordre fait les colonnes. */
|
|
6347
|
+
panels = computed(() => [...this.panelsProjetes(), ...this.panelsPoses()], ...(ngDevMode ? [{ debugName: "panels" }] : /* istanbul ignore next */ []));
|
|
6348
|
+
/** Reçoit la LISTE COMPLÈTE des panneaux posés. L'hôte filtre ce qui n'en est pas un. */
|
|
6349
|
+
enregistrerEnfants(instances) {
|
|
6350
|
+
this.panelsPoses.set(instances.filter((i) => i instanceof CadSplitterPanelComponent));
|
|
6351
|
+
}
|
|
6268
6352
|
sizes = signal([], ...(ngDevMode ? [{ debugName: "sizes" }] : /* istanbul ignore next */ []));
|
|
6269
6353
|
gutters = computed(() => Array.from({ length: Math.max(0, this.panels().length - 1) }, (_, i) => i), ...(ngDevMode ? [{ debugName: "gutters" }] : /* istanbul ignore next */ []));
|
|
6270
6354
|
mins = computed(() => this.panels().map((p, i) => this.minSizes()[i] ?? p.minSize() ?? 0), ...(ngDevMode ? [{ debugName: "mins" }] : /* istanbul ignore next */ []));
|
|
@@ -6340,7 +6424,7 @@ class CadSplitterComponent {
|
|
|
6340
6424
|
this.reset();
|
|
6341
6425
|
}
|
|
6342
6426
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: CadSplitterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
6343
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: CadSplitterComponent, isStandalone: true, selector: "cad-splitter", inputs: { layout: { classPropertyName: "layout", publicName: "layout", isSignal: true, isRequired: false, transformFunction: null }, panelSizes: { classPropertyName: "panelSizes", publicName: "panelSizes", isSignal: true, isRequired: false, transformFunction: null }, minSizes: { classPropertyName: "minSizes", publicName: "minSizes", isSignal: true, isRequired: false, transformFunction: null }, gutterSize: { classPropertyName: "gutterSize", publicName: "gutterSize", isSignal: true, isRequired: false, transformFunction: null }, stateKey: { classPropertyName: "stateKey", publicName: "stateKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { resizeStart: "resizeStart", resizeEnd: "resizeEnd" }, host: { properties: { "class.is-vertical": "layout() === \"vertical\"", "style.--_g.px": "gutterSize()", "style.grid-template-columns": "layout() === \"horizontal\" ? tpl() : null", "style.grid-template-rows": "layout() === \"vertical\" ? tpl() : null" }, classAttribute: "cad-splitter" }, queries: [{ propertyName: "
|
|
6427
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: CadSplitterComponent, isStandalone: true, selector: "cad-splitter", inputs: { layout: { classPropertyName: "layout", publicName: "layout", isSignal: true, isRequired: false, transformFunction: null }, panelSizes: { classPropertyName: "panelSizes", publicName: "panelSizes", isSignal: true, isRequired: false, transformFunction: null }, minSizes: { classPropertyName: "minSizes", publicName: "minSizes", isSignal: true, isRequired: false, transformFunction: null }, gutterSize: { classPropertyName: "gutterSize", publicName: "gutterSize", isSignal: true, isRequired: false, transformFunction: null }, stateKey: { classPropertyName: "stateKey", publicName: "stateKey", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { resizeStart: "resizeStart", resizeEnd: "resizeEnd" }, host: { properties: { "class.is-vertical": "layout() === \"vertical\"", "style.--_g.px": "gutterSize()", "style.grid-template-columns": "layout() === \"horizontal\" ? tpl() : null", "style.grid-template-rows": "layout() === \"vertical\" ? tpl() : null" }, classAttribute: "cad-splitter" }, queries: [{ propertyName: "panelsProjetes", predicate: CadSplitterPanelComponent, isSignal: true }], ngImport: i0, template: `
|
|
6344
6428
|
<ng-content/>
|
|
6345
6429
|
@for (g of gutters(); track g) {
|
|
6346
6430
|
<div class="sp__gutter" role="separator" tabindex="0" [attr.aria-orientation]="layout() === 'horizontal' ? 'vertical' : 'horizontal'" [attr.aria-valuenow]="round(sizes()[g])" [attr.aria-valuemin]="mins()[g]" [attr.aria-valuemax]="100" [style.grid-column]="layout() === 'horizontal' ? g * 2 + 2 : null" [style.grid-row]="layout() === 'vertical' ? g * 2 + 2 : null"
|
|
@@ -6357,7 +6441,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImpo
|
|
|
6357
6441
|
(pointerdown)="onDown($event, g)" (dblclick)="reset()" (keydown)="onKey($event, g)"><i></i></div>
|
|
6358
6442
|
}
|
|
6359
6443
|
`, styles: [":host{display:grid;width:100%;height:100%;min-height:0;min-width:0;--_g: 6px}:host ::ng-deep>cad-splitter-panel{grid-row:1}:host(.is-vertical) ::ng-deep>cad-splitter-panel{grid-row:auto;grid-column:1}:host(:not(.is-vertical)) ::ng-deep>cad-splitter-panel:nth-child(1){grid-column:1}:host(:not(.is-vertical)) ::ng-deep>cad-splitter-panel:nth-child(2){grid-column:3}:host(:not(.is-vertical)) ::ng-deep>cad-splitter-panel:nth-child(3){grid-column:5}:host(:not(.is-vertical)) ::ng-deep>cad-splitter-panel:nth-child(4){grid-column:7}:host(:not(.is-vertical)) ::ng-deep>cad-splitter-panel:nth-child(5){grid-column:9}:host(.is-vertical) ::ng-deep>cad-splitter-panel:nth-child(1){grid-row:1}:host(.is-vertical) ::ng-deep>cad-splitter-panel:nth-child(2){grid-row:3}:host(.is-vertical) ::ng-deep>cad-splitter-panel:nth-child(3){grid-row:5}:host(.is-vertical) ::ng-deep>cad-splitter-panel:nth-child(4){grid-row:7}:host(.is-vertical) ::ng-deep>cad-splitter-panel:nth-child(5){grid-row:9}.sp__gutter{grid-row:1;background:var(--cad-border);display:grid;place-items:center;cursor:col-resize;touch-action:none;-webkit-user-select:none;user-select:none;transition:background var(--cad-dur)}:host(.is-vertical) .sp__gutter{grid-column:1;cursor:row-resize}.sp__gutter i{width:2px;height:22px;border-radius:2px;background:var(--cad-border-strong)}:host(.is-vertical) .sp__gutter i{width:22px;height:2px}.sp__gutter:hover,.sp__gutter.is-active{background:var(--cad-accent-soft)}.sp__gutter:hover i,.sp__gutter.is-active i{background:var(--cad-accent)}.sp__gutter:focus-visible{outline:2px solid var(--cad-ring);outline-offset:-2px}\n"] }]
|
|
6360
|
-
}], ctorParameters: () => [], propDecorators: { layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }], panelSizes: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelSizes", required: false }] }], minSizes: [{ type: i0.Input, args: [{ isSignal: true, alias: "minSizes", required: false }] }], gutterSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "gutterSize", required: false }] }], stateKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "stateKey", required: false }] }], resizeStart: [{ type: i0.Output, args: ["resizeStart"] }], resizeEnd: [{ type: i0.Output, args: ["resizeEnd"] }],
|
|
6444
|
+
}], ctorParameters: () => [], propDecorators: { layout: [{ type: i0.Input, args: [{ isSignal: true, alias: "layout", required: false }] }], panelSizes: [{ type: i0.Input, args: [{ isSignal: true, alias: "panelSizes", required: false }] }], minSizes: [{ type: i0.Input, args: [{ isSignal: true, alias: "minSizes", required: false }] }], gutterSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "gutterSize", required: false }] }], stateKey: [{ type: i0.Input, args: [{ isSignal: true, alias: "stateKey", required: false }] }], resizeStart: [{ type: i0.Output, args: ["resizeStart"] }], resizeEnd: [{ type: i0.Output, args: ["resizeEnd"] }], panelsProjetes: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => CadSplitterPanelComponent), { isSignal: true }] }] } });
|
|
6361
6445
|
|
|
6362
6446
|
const CAD_SHELL = new InjectionToken('CAD_SHELL');
|
|
6363
6447
|
/**
|
|
@@ -8031,6 +8115,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImpo
|
|
|
8031
8115
|
* contenu (ou <ng-template cadTabContent> pour un rendu vraiment paresseux)
|
|
8032
8116
|
* <ng-template cadTabLabel>label custom</ng-template>
|
|
8033
8117
|
* </cad-tab>
|
|
8118
|
+
* @atelier icone=panel-top conteneur=flux dans=cad-tabs pose-label=Onglet
|
|
8034
8119
|
*/
|
|
8035
8120
|
class CadTabComponent {
|
|
8036
8121
|
value = input(undefined, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
@@ -8064,7 +8149,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImpo
|
|
|
8064
8149
|
/**
|
|
8065
8150
|
* <cad-tabs [(value)]="tab" [(activeIndex)]="i" variant="line|pill|enclosed" size="sm|md" [stretch] [scrollable] [lazy]="true" [keepAlive]="true" (changed) (tabChange)>
|
|
8066
8151
|
* `value` prime sur `activeIndex` (les deux sont two-way et synchronisés). Clavier ←/→/Home/End sur la liste.
|
|
8067
|
-
* @atelier icone=folder
|
|
8152
|
+
* @atelier icone=folder conteneur=direct largeur=12 hauteur=6
|
|
8068
8153
|
*/
|
|
8069
8154
|
class CadTabsComponent {
|
|
8070
8155
|
value = model(undefined, ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
@@ -8080,7 +8165,39 @@ class CadTabsComponent {
|
|
|
8080
8165
|
changed = output();
|
|
8081
8166
|
/** Alias PrimeNG-like. */
|
|
8082
8167
|
tabChange = output();
|
|
8083
|
-
|
|
8168
|
+
/** Onglets déclarés dans un GABARIT — la voie normale, celle de tous les usages écrits. */
|
|
8169
|
+
tabsProjetes = contentChildren(CadTabComponent, ...(ngDevMode ? [{ debugName: "tabsProjetes" }] : /* istanbul ignore next */ []));
|
|
8170
|
+
/**
|
|
8171
|
+
* Onglets POSÉS : créés hors gabarit par `createComponent`, et annoncés par
|
|
8172
|
+
* `enregistrerEnfants` — le contrat d'accueil décrit dans `atelier/atelier.pieces.ts`.
|
|
8173
|
+
*
|
|
8174
|
+
* ⚠️ CE N'EST PAS UN DOUBLON DE LA REQUÊTE, C'EST LA SEULE VOIE POSSIBLE POUR EUX.
|
|
8175
|
+
* Mesuré le 27/08 : un `cad-tab` créé impérativement et passé en `projectableNodes`
|
|
8176
|
+
* arrive bien dans le DOM, mais `contentChildren` NE LE VOIT PAS — une requête de
|
|
8177
|
+
* contenu se résout sur la structure déclarée d'un gabarit, et un composant instancié
|
|
8178
|
+
* à la main vit dans une autre vue. Résultat avant correction : `onglets=0`, une barre
|
|
8179
|
+
* vide et aucun panneau, sans la moindre erreur. C'est ce qui rendait `cad-tabs`
|
|
8180
|
+
* inutilisable dans l'atelier et dans les pages visuelles de frontless.
|
|
8181
|
+
*
|
|
8182
|
+
* Même trappe que `cad-button-group`, qui la porte depuis le 24/08 pour la même
|
|
8183
|
+
* raison (il était SOURD aux clics de ses boutons posés) : les deux sources
|
|
8184
|
+
* FUSIONNENT, la projection reste prioritaire dans l'ordre, et rien ne change pour
|
|
8185
|
+
* qui écrit du gabarit.
|
|
8186
|
+
*/
|
|
8187
|
+
tabsPoses = signal([], ...(ngDevMode ? [{ debugName: "tabsPoses" }] : /* istanbul ignore next */ []));
|
|
8188
|
+
/** Tous les onglets : projetés d'abord, posés ensuite. L'ordre fait la barre. */
|
|
8189
|
+
tabs = computed(() => [...this.tabsProjetes(), ...this.tabsPoses()], ...(ngDevMode ? [{ debugName: "tabs" }] : /* istanbul ignore next */ []));
|
|
8190
|
+
/**
|
|
8191
|
+
* Reçoit les instances des onglets posés — la LISTE COMPLÈTE, pas un ajout.
|
|
8192
|
+
*
|
|
8193
|
+
* Le poseur reconstruit ses enfants d'un bloc à chaque changement de structure : lui
|
|
8194
|
+
* faire tenir un différentiel inviterait le fantôme (un onglet détruit qui reste dans
|
|
8195
|
+
* la barre). L'hôte filtre lui-même ce qui n'est pas un onglet, pour qu'un appelant
|
|
8196
|
+
* n'ait pas à connaître nos types.
|
|
8197
|
+
*/
|
|
8198
|
+
enregistrerEnfants(instances) {
|
|
8199
|
+
this.tabsPoses.set(instances.filter((i) => i instanceof CadTabComponent));
|
|
8200
|
+
}
|
|
8084
8201
|
list = viewChild('list', ...(ngDevMode ? [{ debugName: "list" }] : /* istanbul ignore next */ []));
|
|
8085
8202
|
btns = viewChildren('tabBtn', ...(ngDevMode ? [{ debugName: "btns" }] : /* istanbul ignore next */ []));
|
|
8086
8203
|
overflow = signal(false, ...(ngDevMode ? [{ debugName: "overflow" }] : /* istanbul ignore next */ []));
|
|
@@ -8138,7 +8255,7 @@ class CadTabsComponent {
|
|
|
8138
8255
|
el.scrollBy({ left: dir * el.clientWidth * .6 }); }
|
|
8139
8256
|
checkOverflow() { const el = this.list()?.nativeElement; this.overflow.set(!!el && el.scrollWidth > el.clientWidth + 1); }
|
|
8140
8257
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: CadTabsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8141
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: CadTabsComponent, isStandalone: true, selector: "cad-tabs", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, activeIndex: { classPropertyName: "activeIndex", publicName: "activeIndex", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, stretch: { classPropertyName: "stretch", publicName: "stretch", isSignal: true, isRequired: false, transformFunction: null }, scrollable: { classPropertyName: "scrollable", publicName: "scrollable", isSignal: true, isRequired: false, transformFunction: null }, lazy: { classPropertyName: "lazy", publicName: "lazy", isSignal: true, isRequired: false, transformFunction: null }, keepAlive: { classPropertyName: "keepAlive", publicName: "keepAlive", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", activeIndex: "activeIndexChange", changed: "changed", tabChange: "tabChange" }, host: { properties: { "class": "\"cad-tabs var-\" + variant()", "class.size-sm": "size()===\"sm\"", "class.is-stretch": "stretch()" }, classAttribute: "cad-tabs" }, queries: [{ propertyName: "
|
|
8258
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: CadTabsComponent, isStandalone: true, selector: "cad-tabs", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, activeIndex: { classPropertyName: "activeIndex", publicName: "activeIndex", isSignal: true, isRequired: false, transformFunction: null }, variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, stretch: { classPropertyName: "stretch", publicName: "stretch", isSignal: true, isRequired: false, transformFunction: null }, scrollable: { classPropertyName: "scrollable", publicName: "scrollable", isSignal: true, isRequired: false, transformFunction: null }, lazy: { classPropertyName: "lazy", publicName: "lazy", isSignal: true, isRequired: false, transformFunction: null }, keepAlive: { classPropertyName: "keepAlive", publicName: "keepAlive", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", activeIndex: "activeIndexChange", changed: "changed", tabChange: "tabChange" }, host: { properties: { "class": "\"cad-tabs var-\" + variant()", "class.size-sm": "size()===\"sm\"", "class.is-stretch": "stretch()" }, classAttribute: "cad-tabs" }, queries: [{ propertyName: "tabsProjetes", predicate: CadTabComponent, isSignal: true }], viewQueries: [{ propertyName: "list", first: true, predicate: ["list"], descendants: true, isSignal: true }, { propertyName: "btns", predicate: ["tabBtn"], descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
8142
8259
|
<div class="cad-tabs__bar">
|
|
8143
8260
|
@if (scrollable() && overflow()) {<button type="button" class="cad-tabs__arrow" aria-label="Défiler à gauche" (click)="scroll(-1)"><cad-icon name="chevron-left" [size]="14"/></button>}
|
|
8144
8261
|
<div #list class="cad-tabs__list" role="tablist" [class.is-scrollable]="scrollable()" (keydown)="onKey($event)" (scroll)="checkOverflow()">
|
|
@@ -8197,7 +8314,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImpo
|
|
|
8197
8314
|
}
|
|
8198
8315
|
}
|
|
8199
8316
|
`, styles: [":host{display:block;font-family:var(--cad-font);font-size:var(--cad-font-size)}.cad-tabs__bar{display:flex;align-items:stretch;border-bottom:1px solid var(--cad-border)}.cad-tabs__list{display:flex;gap:2px;flex:1;min-width:0}.cad-tabs__list.is-scrollable{overflow-x:auto;scrollbar-width:none;scroll-behavior:smooth}.cad-tabs__list.is-scrollable::-webkit-scrollbar{display:none}:host(.is-stretch) [role=tab]{flex:1;justify-content:center}[role=tab]{position:relative;height:34px;padding:0 12px;border:0;background:transparent;color:var(--cad-fg-secondary);font:500 var(--cad-font-size) var(--cad-font);cursor:pointer;display:inline-flex;align-items:center;gap:6px;white-space:nowrap;border-radius:6px 6px 0 0;transition:color var(--cad-dur),background var(--cad-dur)}:host(.size-sm) [role=tab]{height:28px;padding:0 9px;font-size:var(--cad-font-size-sm)}[role=tab]:hover:not([disabled]){color:var(--cad-fg)}[role=tab]:focus-visible{outline:2px solid var(--cad-ring);outline-offset:-2px}[role=tab][disabled]{opacity:.5;cursor:not-allowed}[role=tab].is-active{color:var(--cad-accent)}[role=tab].is-active:after{content:\"\";position:absolute;left:8px;right:8px;bottom:-1px;height:2px;border-radius:2px;background:var(--cad-accent)}.cad-tabs__count{font:500 10.5px var(--cad-font-mono);padding:1px 6px;border-radius:999px;background:var(--cad-elevated);color:var(--cad-fg-secondary)}[role=tab].is-active .cad-tabs__count{background:var(--cad-accent-soft);color:var(--cad-accent)}.cad-tabs__close{display:inline-grid;place-items:center;width:16px;height:16px;border-radius:4px;color:var(--cad-fg-muted);margin-left:2px}.cad-tabs__close:hover{background:var(--cad-hover);color:var(--cad-fg)}.cad-tabs__arrow{border:0;background:transparent;color:var(--cad-fg-muted);cursor:pointer;padding:0 4px;display:grid;place-items:center}.cad-tabs__arrow:hover{color:var(--cad-fg)}.cad-tabs__panel{padding-top:12px;outline:none}:host(.var-pill) .cad-tabs__bar{border-bottom:0}:host(.var-pill) .cad-tabs__list{gap:4px;padding:3px;background:var(--cad-bg-subtle);border:1px solid var(--cad-border);border-radius:var(--cad-radius);flex:0 1 auto}:host(.var-pill) [role=tab]{height:26px;border-radius:6px;padding:0 10px}:host(.var-pill) [role=tab].is-active{background:var(--cad-surface);color:var(--cad-fg);box-shadow:0 1px 2px #0000001f}:host(.var-pill) [role=tab].is-active:after{display:none}:host(.var-pill) [role=tab].is-active .cad-tabs__count{background:var(--cad-accent-soft);color:var(--cad-accent)}:host(.var-enclosed) [role=tab]{border:1px solid transparent;border-bottom:0;margin-bottom:-1px}:host(.var-enclosed) [role=tab].is-active{background:var(--cad-surface);border-color:var(--cad-border);color:var(--cad-fg)}:host(.var-enclosed) [role=tab].is-active:after{display:none}\n"] }]
|
|
8200
|
-
}], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], activeIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeIndex", required: false }] }, { type: i0.Output, args: ["activeIndexChange"] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], stretch: [{ type: i0.Input, args: [{ isSignal: true, alias: "stretch", required: false }] }], scrollable: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollable", required: false }] }], lazy: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazy", required: false }] }], keepAlive: [{ type: i0.Input, args: [{ isSignal: true, alias: "keepAlive", required: false }] }], changed: [{ type: i0.Output, args: ["changed"] }], tabChange: [{ type: i0.Output, args: ["tabChange"] }],
|
|
8317
|
+
}], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], activeIndex: [{ type: i0.Input, args: [{ isSignal: true, alias: "activeIndex", required: false }] }, { type: i0.Output, args: ["activeIndexChange"] }], variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], stretch: [{ type: i0.Input, args: [{ isSignal: true, alias: "stretch", required: false }] }], scrollable: [{ type: i0.Input, args: [{ isSignal: true, alias: "scrollable", required: false }] }], lazy: [{ type: i0.Input, args: [{ isSignal: true, alias: "lazy", required: false }] }], keepAlive: [{ type: i0.Input, args: [{ isSignal: true, alias: "keepAlive", required: false }] }], changed: [{ type: i0.Output, args: ["changed"] }], tabChange: [{ type: i0.Output, args: ["tabChange"] }], tabsProjetes: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => CadTabComponent), { isSignal: true }] }], list: [{ type: i0.ViewChild, args: ['list', { isSignal: true }] }], btns: [{ type: i0.ViewChildren, args: ['tabBtn', { isSignal: true }] }] } });
|
|
8201
8318
|
|
|
8202
8319
|
/** <cad-step label="Domaine" description="…" icon [optional] [disabled] [completed] [state]="'error'"> contenu optionnel </cad-step> */
|
|
8203
8320
|
class CadStepComponent {
|
|
@@ -8370,9 +8487,31 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImpo
|
|
|
8370
8487
|
* </cad-accordion-panel>
|
|
8371
8488
|
* </cad-accordion>
|
|
8372
8489
|
* `value` = valeur ouverte (string) ou tableau si `multiple`. Clavier : Entrée/Espace, ↑/↓/Home/End entre en-têtes.
|
|
8490
|
+
* @atelier icone=panel-top conteneur=flux dans=cad-accordion pose-header=Section
|
|
8373
8491
|
*/
|
|
8374
8492
|
class CadAccordionPanelComponent {
|
|
8375
|
-
|
|
8493
|
+
/**
|
|
8494
|
+
* L'accordéon d'accueil — INJECTÉ dans un gabarit, POUSSÉ par l'hôte quand la pièce
|
|
8495
|
+
* est posée hors gabarit.
|
|
8496
|
+
*
|
|
8497
|
+
* ⚠️ L'INJECTION EST OPTIONNELLE, ET C'EST LE CŒUR DU CORRECTIF (SZU 27/08 : « pourquoi
|
|
8498
|
+
* cad-accordion serait différent d'un cad-tabs ? »). Elle était obligatoire, donc :
|
|
8499
|
+
* `NG0201` dès qu'on créait le panneau à la main, et `gen-catalog` le classait
|
|
8500
|
+
* « contextuel » — il n'était même pas POSABLE. Or `cad-tab`, lui, n'injecte rien :
|
|
8501
|
+
* c'est une pièce PASSIVE que son hôte pilote. La différence n'était pas une contrainte
|
|
8502
|
+
* du composant, c'était une divergence d'écriture entre deux familles jumelles.
|
|
8503
|
+
*
|
|
8504
|
+
* Renversement : la pièce ne va plus CHERCHER son hôte, c'est l'hôte qui s'annonce en
|
|
8505
|
+
* l'accueillant (`rattacher`). Un panneau posé seul reste sensé — il gère alors son
|
|
8506
|
+
* propre `expanded` au lieu de lever.
|
|
8507
|
+
*/
|
|
8508
|
+
accInjecte = inject(forwardRef(() => CadAccordionComponent), { optional: true });
|
|
8509
|
+
accPose = signal(null, ...(ngDevMode ? [{ debugName: "accPose" }] : /* istanbul ignore next */ []));
|
|
8510
|
+
acc = computed(() => this.accInjecte ?? this.accPose(), ...(ngDevMode ? [{ debugName: "acc" }] : /* istanbul ignore next */ []));
|
|
8511
|
+
/** L'accordéon s'annonce à la pièce qu'il accueille. Cf. `atelier/atelier.pieces.ts`. */
|
|
8512
|
+
rattacher(acc) {
|
|
8513
|
+
this.accPose.set(acc);
|
|
8514
|
+
}
|
|
8376
8515
|
value = input(cadId('cad-panel'), ...(ngDevMode ? [{ debugName: "value" }] : /* istanbul ignore next */ []));
|
|
8377
8516
|
header = input('', ...(ngDevMode ? [{ debugName: "header" }] : /* istanbul ignore next */ []));
|
|
8378
8517
|
icon = input('', ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
|
|
@@ -8385,7 +8524,8 @@ class CadAccordionPanelComponent {
|
|
|
8385
8524
|
contentTpl = contentChild(CadPanelContentDirective, ...(ngDevMode ? [{ debugName: "contentTpl" }] : /* istanbul ignore next */ []));
|
|
8386
8525
|
id = cadId('cad-acc');
|
|
8387
8526
|
rendered = signal(false, ...(ngDevMode ? [{ debugName: "rendered" }] : /* istanbul ignore next */ []));
|
|
8388
|
-
|
|
8527
|
+
/** Sans hôte, le panneau fait autorité sur lui-même : posé seul, il reste utilisable. */
|
|
8528
|
+
isOpen = computed(() => this.acc()?.isOpen(this.value()) ?? this.expanded(), ...(ngDevMode ? [{ debugName: "isOpen" }] : /* istanbul ignore next */ []));
|
|
8389
8529
|
constructor() {
|
|
8390
8530
|
effect(() => { if (this.isOpen())
|
|
8391
8531
|
this.rendered.set(true); });
|
|
@@ -8409,18 +8549,25 @@ class CadAccordionPanelComponent {
|
|
|
8409
8549
|
if (e === precedent)
|
|
8410
8550
|
return;
|
|
8411
8551
|
precedent = e;
|
|
8412
|
-
untracked(() => { if (e !==
|
|
8413
|
-
|
|
8552
|
+
untracked(() => { const a = this.acc(); if (a && e !== a.isOpen(this.value()))
|
|
8553
|
+
a.setOpen(this.value(), e, this); });
|
|
8414
8554
|
});
|
|
8415
8555
|
}
|
|
8416
|
-
toggle() {
|
|
8417
|
-
|
|
8556
|
+
toggle() {
|
|
8557
|
+
if (this.disabled())
|
|
8558
|
+
return;
|
|
8559
|
+
const a = this.acc();
|
|
8560
|
+
if (a)
|
|
8561
|
+
a.setOpen(this.value(), !this.isOpen(), this);
|
|
8562
|
+
else
|
|
8563
|
+
this.expanded.set(!this.expanded()); // panneau solitaire : il se gère lui-même
|
|
8564
|
+
}
|
|
8418
8565
|
focus() { document.getElementById(this.id + '-h')?.focus(); }
|
|
8419
8566
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: CadAccordionPanelComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8420
8567
|
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: CadAccordionPanelComponent, isStandalone: true, selector: "cad-accordion-panel", inputs: { value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, header: { classPropertyName: "header", publicName: "header", isSignal: true, isRequired: false, transformFunction: null }, icon: { classPropertyName: "icon", publicName: "icon", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, expanded: { classPropertyName: "expanded", publicName: "expanded", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { expanded: "expandedChange", opened: "opened", closed: "closed" }, host: { properties: { "class.is-open": "isOpen()", "class.is-disabled": "disabled()" }, classAttribute: "cad-accordion-panel" }, queries: [{ propertyName: "headerTpl", first: true, predicate: CadPanelHeaderDirective, descendants: true, isSignal: true }, { propertyName: "contentTpl", first: true, predicate: CadPanelContentDirective, descendants: true, isSignal: true }], ngImport: i0, template: `
|
|
8421
8568
|
<h3 class="cad-acc__h">
|
|
8422
|
-
<button type="button" class="cad-acc__hd" [id]="id + '-h'" [attr.aria-expanded]="isOpen()" [attr.aria-controls]="id + '-c'" [disabled]="disabled()" (click)="toggle()" (keydown)="acc
|
|
8423
|
-
<cad-icon class="cad-acc__chev" [name]="acc
|
|
8569
|
+
<button type="button" class="cad-acc__hd" [id]="id + '-h'" [attr.aria-expanded]="isOpen()" [attr.aria-controls]="id + '-c'" [disabled]="disabled()" (click)="toggle()" (keydown)="acc()?.onKey($event, this)">
|
|
8570
|
+
<cad-icon class="cad-acc__chev" [name]="acc()?.expandIcon() ?? 'chevron-right'" [size]="13"/>
|
|
8424
8571
|
@if (icon()) {<cad-icon [name]="icon()" [size]="14"/>}
|
|
8425
8572
|
@if (headerTpl()) { <ng-container [ngTemplateOutlet]="headerTpl()!.tpl" /> } @else { <span class="cad-acc__title">{{ header() }}</span> }
|
|
8426
8573
|
<span class="cad-acc__extra"><ng-content select="[cadPanelExtra]" /></span>
|
|
@@ -8440,8 +8587,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImpo
|
|
|
8440
8587
|
type: Component,
|
|
8441
8588
|
args: [{ selector: 'cad-accordion-panel', standalone: true, imports: [NgTemplateOutlet, CadIconComponent], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'cad-accordion-panel', '[class.is-open]': 'isOpen()', '[class.is-disabled]': 'disabled()' }, template: `
|
|
8442
8589
|
<h3 class="cad-acc__h">
|
|
8443
|
-
<button type="button" class="cad-acc__hd" [id]="id + '-h'" [attr.aria-expanded]="isOpen()" [attr.aria-controls]="id + '-c'" [disabled]="disabled()" (click)="toggle()" (keydown)="acc
|
|
8444
|
-
<cad-icon class="cad-acc__chev" [name]="acc
|
|
8590
|
+
<button type="button" class="cad-acc__hd" [id]="id + '-h'" [attr.aria-expanded]="isOpen()" [attr.aria-controls]="id + '-c'" [disabled]="disabled()" (click)="toggle()" (keydown)="acc()?.onKey($event, this)">
|
|
8591
|
+
<cad-icon class="cad-acc__chev" [name]="acc()?.expandIcon() ?? 'chevron-right'" [size]="13"/>
|
|
8445
8592
|
@if (icon()) {<cad-icon [name]="icon()" [size]="14"/>}
|
|
8446
8593
|
@if (headerTpl()) { <ng-container [ngTemplateOutlet]="headerTpl()!.tpl" /> } @else { <span class="cad-acc__title">{{ header() }}</span> }
|
|
8447
8594
|
<span class="cad-acc__extra"><ng-content select="[cadPanelExtra]" /></span>
|
|
@@ -8457,7 +8604,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImpo
|
|
|
8457
8604
|
</div>
|
|
8458
8605
|
`, styles: [":host{display:block;border-bottom:1px solid var(--cad-border);font-family:var(--cad-font);font-size:var(--cad-font-size)}:host(:last-child){border-bottom:0}.cad-acc__h{margin:0;font:inherit}.cad-acc__hd{all:unset;box-sizing:border-box;display:flex;align-items:center;gap:8px;width:100%;padding:9px 12px;font-weight:500;cursor:pointer;background:var(--cad-bg-subtle);color:var(--cad-fg);transition:background var(--cad-dur)}.cad-acc__hd:hover:not([disabled]){background:var(--cad-hover)}.cad-acc__hd:focus-visible{outline:2px solid var(--cad-ring);outline-offset:-2px}.cad-acc__hd[disabled]{cursor:not-allowed;opacity:.55}.cad-acc__chev{color:var(--cad-fg-muted);transition:transform .16s var(--cad-ease)}:host(.is-open) .cad-acc__chev{transform:rotate(90deg)}.cad-acc__title{flex:1}.cad-acc__extra{margin-left:auto;display:inline-flex;gap:6px}.cad-acc__wrap{display:grid;grid-template-rows:0fr;transition:grid-template-rows .16s var(--cad-ease)}:host(.is-open) .cad-acc__wrap{grid-template-rows:1fr}.cad-acc__inner{overflow:hidden;min-height:0}.cad-acc__bd{padding:10px 12px 12px;font-size:12.5px;color:var(--cad-fg-secondary)}@media(prefers-reduced-motion:reduce){.cad-acc__wrap,.cad-acc__chev{transition:none}}\n"] }]
|
|
8459
8606
|
}], ctorParameters: () => [], propDecorators: { value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }], header: [{ type: i0.Input, args: [{ isSignal: true, alias: "header", required: false }] }], icon: [{ type: i0.Input, args: [{ isSignal: true, alias: "icon", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], expanded: [{ type: i0.Input, args: [{ isSignal: true, alias: "expanded", required: false }] }, { type: i0.Output, args: ["expandedChange"] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }], headerTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => CadPanelHeaderDirective), { isSignal: true }] }], contentTpl: [{ type: i0.ContentChild, args: [i0.forwardRef(() => CadPanelContentDirective), { isSignal: true }] }] } });
|
|
8460
|
-
/** @atelier icone=chevron-down */
|
|
8607
|
+
/** @atelier icone=chevron-down conteneur=direct largeur=12 hauteur=8 */
|
|
8461
8608
|
class CadAccordionComponent {
|
|
8462
8609
|
multiple = input(false, { ...(ngDevMode ? { debugName: "multiple" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
8463
8610
|
/** Ouvert(s) : string (single) ou string[] (multiple). */
|
|
@@ -8466,7 +8613,20 @@ class CadAccordionComponent {
|
|
|
8466
8613
|
/** Sans bordure extérieure. */
|
|
8467
8614
|
flush = input(false, { ...(ngDevMode ? { debugName: "flush" } : /* istanbul ignore next */ {}), transform: booleanAttribute });
|
|
8468
8615
|
changed = output();
|
|
8469
|
-
|
|
8616
|
+
panelsProjetes = contentChildren(CadAccordionPanelComponent, ...(ngDevMode ? [{ debugName: "panelsProjetes" }] : /* istanbul ignore next */ []));
|
|
8617
|
+
/** Panneaux POSÉS hors gabarit, annoncés par `enregistrerEnfants`. */
|
|
8618
|
+
panelsPoses = signal([], ...(ngDevMode ? [{ debugName: "panelsPoses" }] : /* istanbul ignore next */ []));
|
|
8619
|
+
panels = computed(() => [...this.panelsProjetes(), ...this.panelsPoses()], ...(ngDevMode ? [{ debugName: "panels" }] : /* istanbul ignore next */ []));
|
|
8620
|
+
/**
|
|
8621
|
+
* Reçoit la LISTE COMPLÈTE des panneaux posés, et se RATTACHE à chacun : la pièce
|
|
8622
|
+
* n'ayant plus d'injection obligatoire, c'est ce geste qui rétablit le lien.
|
|
8623
|
+
*/
|
|
8624
|
+
enregistrerEnfants(instances) {
|
|
8625
|
+
const pieces = instances.filter((i) => i instanceof CadAccordionPanelComponent);
|
|
8626
|
+
for (const p of pieces)
|
|
8627
|
+
p.rattacher(this);
|
|
8628
|
+
this.panelsPoses.set(pieces);
|
|
8629
|
+
}
|
|
8470
8630
|
openSet = computed(() => { const v = this.value(); return new Set(v == null ? [] : Array.isArray(v) ? v : [v]); }, ...(ngDevMode ? [{ debugName: "openSet" }] : /* istanbul ignore next */ []));
|
|
8471
8631
|
isOpen(v) { return this.openSet().has(v); }
|
|
8472
8632
|
setOpen(v, open, panel) {
|
|
@@ -8504,12 +8664,12 @@ class CadAccordionComponent {
|
|
|
8504
8664
|
t?.focus();
|
|
8505
8665
|
}
|
|
8506
8666
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: CadAccordionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
8507
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.20", type: CadAccordionComponent, isStandalone: true, selector: "cad-accordion", inputs: { multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, expandIcon: { classPropertyName: "expandIcon", publicName: "expandIcon", isSignal: true, isRequired: false, transformFunction: null }, flush: { classPropertyName: "flush", publicName: "flush", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", changed: "changed" }, host: { properties: { "class.is-flush": "flush()" }, classAttribute: "cad-accordion" }, queries: [{ propertyName: "
|
|
8667
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.2.20", type: CadAccordionComponent, isStandalone: true, selector: "cad-accordion", inputs: { multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null }, expandIcon: { classPropertyName: "expandIcon", publicName: "expandIcon", isSignal: true, isRequired: false, transformFunction: null }, flush: { classPropertyName: "flush", publicName: "flush", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", changed: "changed" }, host: { properties: { "class.is-flush": "flush()" }, classAttribute: "cad-accordion" }, queries: [{ propertyName: "panelsProjetes", predicate: CadAccordionPanelComponent, isSignal: true }], ngImport: i0, template: `<ng-content />`, isInline: true, styles: [":host{display:block;border:1px solid var(--cad-border);border-radius:var(--cad-radius);overflow:hidden;background:var(--cad-surface)}:host(.is-flush){border:0;border-radius:0;background:transparent}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
8508
8668
|
}
|
|
8509
8669
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: CadAccordionComponent, decorators: [{
|
|
8510
8670
|
type: Component,
|
|
8511
8671
|
args: [{ selector: 'cad-accordion', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'cad-accordion', '[class.is-flush]': 'flush()' }, template: `<ng-content />`, styles: [":host{display:block;border:1px solid var(--cad-border);border-radius:var(--cad-radius);overflow:hidden;background:var(--cad-surface)}:host(.is-flush){border:0;border-radius:0;background:transparent}\n"] }]
|
|
8512
|
-
}], propDecorators: { multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], expandIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandIcon", required: false }] }], flush: [{ type: i0.Input, args: [{ isSignal: true, alias: "flush", required: false }] }], changed: [{ type: i0.Output, args: ["changed"] }],
|
|
8672
|
+
}], propDecorators: { multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], expandIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "expandIcon", required: false }] }], flush: [{ type: i0.Input, args: [{ isSignal: true, alias: "flush", required: false }] }], changed: [{ type: i0.Output, args: ["changed"] }], panelsProjetes: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => CadAccordionPanelComponent), { isSignal: true }] }] } });
|
|
8513
8673
|
|
|
8514
8674
|
class CadBreadcrumbItemDirective {
|
|
8515
8675
|
tpl;
|
|
@@ -12708,6 +12868,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImpo
|
|
|
12708
12868
|
* @atelier ajustement=naturel icone=user-round largeur=1 hauteur=1 pose-text=AB
|
|
12709
12869
|
*/
|
|
12710
12870
|
class CadAvatarComponent {
|
|
12871
|
+
/**
|
|
12872
|
+
* Son élément, exposé comme `cad-button` le fait déjà : le groupe marque le
|
|
12873
|
+
* débordement (`.is-overflow`) sur les éléments, et une requête de contenu ne les
|
|
12874
|
+
* rapporte pas pour un avatar POSÉ hors gabarit.
|
|
12875
|
+
*/
|
|
12876
|
+
el = inject(ElementRef);
|
|
12711
12877
|
src = input(null, ...(ngDevMode ? [{ debugName: "src" }] : /* istanbul ignore next */ []));
|
|
12712
12878
|
text = input('', ...(ngDevMode ? [{ debugName: "text" }] : /* istanbul ignore next */ []));
|
|
12713
12879
|
icon = input('user', ...(ngDevMode ? [{ debugName: "icon" }] : /* istanbul ignore next */ []));
|
|
@@ -13200,26 +13366,41 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImpo
|
|
|
13200
13366
|
/**
|
|
13201
13367
|
* <cad-avatar-group [max]="3" size="md"><cad-avatar text="SZ"/><cad-avatar text="PA"/>…</cad-avatar-group>
|
|
13202
13368
|
* Avatars empilés (chevauchement, bordure surface) ; au-delà de `max` un avatar « +N » (title = noms masqués).
|
|
13203
|
-
* @atelier ajustement=naturel icone=users largeur=2 hauteur=1
|
|
13369
|
+
* @atelier ajustement=naturel icone=users largeur=2 hauteur=1 conteneur=direct accepte=cad-avatar
|
|
13204
13370
|
*/
|
|
13205
13371
|
class CadAvatarGroupComponent {
|
|
13206
13372
|
max = input(null, { ...(ngDevMode ? { debugName: "max" } : /* istanbul ignore next */ {}), transform: v => (v == null || v === '' ? null : Number(v)) });
|
|
13207
13373
|
size = input('md', ...(ngDevMode ? [{ debugName: "size" }] : /* istanbul ignore next */ []));
|
|
13208
13374
|
moreColor = input('#94a3b8', ...(ngDevMode ? [{ debugName: "moreColor" }] : /* istanbul ignore next */ []));
|
|
13209
|
-
|
|
13210
|
-
|
|
13375
|
+
avatarsProjetes = contentChildren(CadAvatarComponent, ...(ngDevMode ? [{ debugName: "avatarsProjetes" }] : /* istanbul ignore next */ []));
|
|
13376
|
+
/**
|
|
13377
|
+
* Avatars POSÉS hors gabarit, annoncés par `enregistrerEnfants`
|
|
13378
|
+
* (cf. `atelier/atelier.pieces.ts`).
|
|
13379
|
+
*
|
|
13380
|
+
* Le groupe RENDAIT correctement sans eux — le chevauchement et les bordures sont du
|
|
13381
|
+
* CSS sur les enfants directs. Seul `max` était inerte : le « +N » ne comptait rien et
|
|
13382
|
+
* rien ne passait en débordement. Une panne discrète, donc pire qu'une panne franche.
|
|
13383
|
+
*/
|
|
13384
|
+
avatarsPoses = signal([], ...(ngDevMode ? [{ debugName: "avatarsPoses" }] : /* istanbul ignore next */ []));
|
|
13385
|
+
avatars = computed(() => [...this.avatarsProjetes(), ...this.avatarsPoses()], ...(ngDevMode ? [{ debugName: "avatars" }] : /* istanbul ignore next */ []));
|
|
13386
|
+
/** Reçoit la LISTE COMPLÈTE des avatars posés. Le groupe filtre ce qui n'en est pas un. */
|
|
13387
|
+
enregistrerEnfants(instances) {
|
|
13388
|
+
this.avatarsPoses.set(instances.filter((i) => i instanceof CadAvatarComponent));
|
|
13389
|
+
}
|
|
13211
13390
|
hidden = computed(() => { const m = this.max(); const n = this.avatars().length; return m != null && n > m ? n - m : 0; }, ...(ngDevMode ? [{ debugName: "hidden" }] : /* istanbul ignore next */ []));
|
|
13212
13391
|
hiddenTitle = computed(() => { const m = this.max() ?? Infinity; return this.avatars().slice(m).map(a => a.label() || a.text()).filter(Boolean).join(', '); }, ...(ngDevMode ? [{ debugName: "hiddenTitle" }] : /* istanbul ignore next */ []));
|
|
13213
13392
|
constructor() {
|
|
13214
|
-
|
|
13393
|
+
// Le marquage du débordement passe par l'ÉLÉMENT de chaque avatar (`el`), et non par
|
|
13394
|
+
// une seconde requête de contenu : celle-ci ne rapporterait rien pour un avatar posé.
|
|
13395
|
+
effect(() => { const m = this.max() ?? Infinity; this.avatars().forEach((a, i) => a.el.nativeElement.classList.toggle('is-overflow', i >= m)); });
|
|
13215
13396
|
}
|
|
13216
13397
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: CadAvatarGroupComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
13217
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: CadAvatarGroupComponent, isStandalone: true, selector: "cad-avatar-group", inputs: { max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, moreColor: { classPropertyName: "moreColor", publicName: "moreColor", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "group" }, properties: { "class.size-sm": "size() === \"sm\"", "class.size-lg": "size() === \"lg\"" }, classAttribute: "cad-avatar-group" }, queries: [{ propertyName: "
|
|
13398
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.20", type: CadAvatarGroupComponent, isStandalone: true, selector: "cad-avatar-group", inputs: { max: { classPropertyName: "max", publicName: "max", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, moreColor: { classPropertyName: "moreColor", publicName: "moreColor", isSignal: true, isRequired: false, transformFunction: null } }, host: { attributes: { "role": "group" }, properties: { "class.size-sm": "size() === \"sm\"", "class.size-lg": "size() === \"lg\"" }, classAttribute: "cad-avatar-group" }, queries: [{ propertyName: "avatarsProjetes", predicate: CadAvatarComponent, isSignal: true }], ngImport: i0, template: `<ng-content/>@if (hidden() > 0) {<cad-avatar class="more" [text]="'+' + hidden()" [size]="size()" [color]="moreColor()" [attr.title]="hiddenTitle()" [label]="hiddenTitle()"/>}`, isInline: true, styles: [":host{display:inline-flex;align-items:center;padding-left:8px}:host ::ng-deep>cad-avatar,.more{margin-left:-8px;box-shadow:0 0 0 2px var(--cad-surface);border-radius:50%}:host(.size-sm) ::ng-deep>cad-avatar,:host(.size-sm) .more{margin-left:-6px}:host(.size-lg) ::ng-deep>cad-avatar,:host(.size-lg) .more{margin-left:-10px}:host ::ng-deep>cad-avatar.is-overflow{display:none}:host ::ng-deep>cad-avatar:hover{z-index:1;position:relative}\n"], dependencies: [{ kind: "component", type: CadAvatarComponent, selector: "cad-avatar", inputs: ["src", "text", "icon", "size", "shape", "color", "label"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
13218
13399
|
}
|
|
13219
13400
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.20", ngImport: i0, type: CadAvatarGroupComponent, decorators: [{
|
|
13220
13401
|
type: Component,
|
|
13221
13402
|
args: [{ selector: 'cad-avatar-group', standalone: true, imports: [CadAvatarComponent], changeDetection: ChangeDetectionStrategy.OnPush, host: { class: 'cad-avatar-group', '[class.size-sm]': 'size() === "sm"', '[class.size-lg]': 'size() === "lg"', role: 'group' }, template: `<ng-content/>@if (hidden() > 0) {<cad-avatar class="more" [text]="'+' + hidden()" [size]="size()" [color]="moreColor()" [attr.title]="hiddenTitle()" [label]="hiddenTitle()"/>}`, styles: [":host{display:inline-flex;align-items:center;padding-left:8px}:host ::ng-deep>cad-avatar,.more{margin-left:-8px;box-shadow:0 0 0 2px var(--cad-surface);border-radius:50%}:host(.size-sm) ::ng-deep>cad-avatar,:host(.size-sm) .more{margin-left:-6px}:host(.size-lg) ::ng-deep>cad-avatar,:host(.size-lg) .more{margin-left:-10px}:host ::ng-deep>cad-avatar.is-overflow{display:none}:host ::ng-deep>cad-avatar:hover{z-index:1;position:relative}\n"] }]
|
|
13222
|
-
}], ctorParameters: () => [], propDecorators: { max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], moreColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "moreColor", required: false }] }],
|
|
13403
|
+
}], ctorParameters: () => [], propDecorators: { max: [{ type: i0.Input, args: [{ isSignal: true, alias: "max", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], moreColor: [{ type: i0.Input, args: [{ isSignal: true, alias: "moreColor", required: false }] }], avatarsProjetes: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => CadAvatarComponent), { isSignal: true }] }] } });
|
|
13223
13404
|
|
|
13224
13405
|
/** `<ng-template cadMeterLabel let-v let-pct="percent">` */
|
|
13225
13406
|
class CadMeterLabelDirective {
|
|
@@ -14204,6 +14385,30 @@ class CadMapComponent {
|
|
|
14204
14385
|
}
|
|
14205
14386
|
catch { /* ignore */ }
|
|
14206
14387
|
} }
|
|
14388
|
+
/**
|
|
14389
|
+
* Contrat d'accueil des pièces POSÉES (cf. `atelier/atelier.pieces.ts`).
|
|
14390
|
+
*
|
|
14391
|
+
* ⚠️ CORRIGE UN MENSONGE LIVRÉ LE 24/08. `cad-map` était annoté conteneur et ses onze
|
|
14392
|
+
* pièces déclaraient `dans=cad-map`, mais AUCUNE couche posée ne s'est jamais
|
|
14393
|
+
* enregistrée : la carte n'exposait que `registerChild`, que les poseurs n'appellent
|
|
14394
|
+
* pas, et `cad-map-layer` s'injecte la carte en `optional` — donc `null` sans chaîne
|
|
14395
|
+
* d'injecteurs, donc pas d'auto-enregistrement, et pas la moindre erreur pour le dire.
|
|
14396
|
+
* Deux vocabulaires pour un besoin : c'est la divergence qu'on paie ici.
|
|
14397
|
+
*
|
|
14398
|
+
* Liste COMPLÈTE à chaque appel : le poseur reconstruit ses enfants d'un bloc, et un
|
|
14399
|
+
* contrat incrémental laisserait des couches fantômes sur la carte.
|
|
14400
|
+
*/
|
|
14401
|
+
enregistrerEnfants(instances) {
|
|
14402
|
+
const pieces = instances.filter((i) => {
|
|
14403
|
+
const k = i;
|
|
14404
|
+
return !!k && typeof k.attach === 'function' && typeof k.ownedIds === 'function';
|
|
14405
|
+
});
|
|
14406
|
+
for (const k of this.extraChildren())
|
|
14407
|
+
if (!pieces.includes(k))
|
|
14408
|
+
this.unregisterChild(k);
|
|
14409
|
+
for (const k of pieces)
|
|
14410
|
+
this.registerChild(k);
|
|
14411
|
+
}
|
|
14207
14412
|
/** Événements du chrome intégré (dessin, import). */
|
|
14208
14413
|
drawChange = output();
|
|
14209
14414
|
layerImport = output();
|
|
@@ -23174,367 +23379,73 @@ const ATELIER_BORNES = {
|
|
|
23174
23379
|
propsMax: 30,
|
|
23175
23380
|
/** Enfants directs d'un conteneur. Le plafond GLOBAL reste `itemsMax`, enfants compris. */
|
|
23176
23381
|
enfantsMax: 30,
|
|
23382
|
+
/**
|
|
23383
|
+
* Profondeur d'imbrication, en niveaux SOUS le plan.
|
|
23384
|
+
*
|
|
23385
|
+
* Un item du plan est à la profondeur 0, son enfant à 1, et ainsi de suite jusqu'à
|
|
23386
|
+
* `profondeurMax` INCLUS — soit cinq étages en tout. Ce n'est pas une préférence
|
|
23387
|
+
* d'ergonomie : `atelierNormaliser` et l'assainisseur backend descendent une
|
|
23388
|
+
* structure VENUE DE L'EXTÉRIEUR (lien partagé, fichier collé), et une récursion
|
|
23389
|
+
* non bornée sur du JSON hostile fait sauter la pile. Le plafond de COMPTE
|
|
23390
|
+
* (`itemsMax`) ne borne pas la profondeur : deux cents items peuvent former une
|
|
23391
|
+
* chaîne de deux cents étages.
|
|
23392
|
+
*
|
|
23393
|
+
* Cinq étages couvrent le besoin réel mesuré le 27/08 — le pire cas de la
|
|
23394
|
+
* bibliothèque est `cad-splitter > cad-splitter-panel > cad-tabs > cad-tab >
|
|
23395
|
+
* contenu`, soit une profondeur de 4 pour le contenu.
|
|
23396
|
+
*/
|
|
23397
|
+
profondeurMax: 4,
|
|
23177
23398
|
};
|
|
23178
23399
|
/** Un plan vide, jamais `null` : un canevas absent et un canevas vide se traitent pareil. */
|
|
23179
23400
|
const atelierLayoutVide = () => ({ version: 1, items: [] });
|
|
23180
23401
|
|
|
23181
23402
|
/**
|
|
23182
|
-
*
|
|
23403
|
+
* Le contrat d'accueil entre un HÔTE de la bibliothèque et les pièces qu'on lui POSE.
|
|
23183
23404
|
*
|
|
23184
|
-
*
|
|
23185
|
-
* calendrier ont tous été trouvés là, et deux fois c'est mon ATTENTE de test qui était
|
|
23186
|
-
* fausse, pas le code — c'est plus facile à voir sur une fonction pure.
|
|
23405
|
+
* ── POURQUOI CE FICHIER EXISTE ──────────────────────────────────────────────────
|
|
23187
23406
|
*
|
|
23188
|
-
*
|
|
23189
|
-
*
|
|
23190
|
-
|
|
23191
|
-
|
|
23192
|
-
let compteur = 0;
|
|
23193
|
-
/** Identifiant conforme à l'assainisseur backend : `/^[A-Za-z0-9_-]{1,24}$/`. */
|
|
23194
|
-
function atelierNouvelId() {
|
|
23195
|
-
compteur += 1;
|
|
23196
|
-
return `i${compteur.toString(36)}`;
|
|
23197
|
-
}
|
|
23198
|
-
/** Remet le compteur à zéro. Réservé aux tests, pour qu'ils ne dépendent pas de leur ordre. */
|
|
23199
|
-
function atelierReinitialiserIds() {
|
|
23200
|
-
compteur = 0;
|
|
23201
|
-
}
|
|
23202
|
-
const borne = (v, min, max) => Math.max(min, Math.min(max, Math.trunc(Number.isFinite(v) ? v : min)));
|
|
23203
|
-
/**
|
|
23204
|
-
* La carte d'occupation du plan, ligne par ligne.
|
|
23407
|
+
* L'atelier du studio et le rendu frontless du shell instancient les composants
|
|
23408
|
+
* IMPÉRATIVEMENT (`createComponent` + `projectableNodes`) : c'est ce qui permet de poser
|
|
23409
|
+
* le VRAI composant, vivant, plutôt qu'une image de lui. Mais deux mécanismes d'Angular
|
|
23410
|
+
* ne traversent PAS cette frontière, et c'est mesuré, pas supposé (27/08) :
|
|
23205
23411
|
*
|
|
23206
|
-
*
|
|
23207
|
-
*
|
|
23208
|
-
|
|
23209
|
-
|
|
23210
|
-
|
|
23211
|
-
|
|
23212
|
-
|
|
23213
|
-
|
|
23214
|
-
|
|
23215
|
-
let ligne = lignes.get(y);
|
|
23216
|
-
if (!ligne) {
|
|
23217
|
-
ligne = new Array(ATELIER_COLONNES).fill(false);
|
|
23218
|
-
lignes.set(y, ligne);
|
|
23219
|
-
}
|
|
23220
|
-
for (let x = it.x; x < it.x + it.w && x < ATELIER_COLONNES; x++)
|
|
23221
|
-
ligne[x] = true;
|
|
23222
|
-
}
|
|
23223
|
-
}
|
|
23224
|
-
return lignes;
|
|
23225
|
-
}
|
|
23226
|
-
/**
|
|
23227
|
-
* La première position libre pour un bloc de `w × h`, en balayant de haut en bas puis de
|
|
23228
|
-
* gauche à droite.
|
|
23412
|
+
* ① `contentChildren()` — une requête de contenu se résout sur la structure DÉCLARÉE
|
|
23413
|
+
* d'un gabarit. Un composant instancié à la main vit dans une autre vue : il arrive
|
|
23414
|
+
* bien dans le DOM, la requête ne le voit jamais. `cad-tabs` rendait `onglets=0`,
|
|
23415
|
+
* `cad-splitter` `gouttieres=0` — une barre vide, aucune erreur.
|
|
23416
|
+
* ② `inject(Hôte)` depuis la pièce — sans chaîne d'injecteurs de nœud, la recherche
|
|
23417
|
+
* remonte à l'injecteur d'environnement et échoue : `NG0201` pour
|
|
23418
|
+
* `cad-accordion-panel` et `cad-radio` (que `gen-catalog` classe d'ailleurs en
|
|
23419
|
+
* « contextuels », donc non posables), ou `null` silencieux quand l'injection est
|
|
23420
|
+
* `optional`.
|
|
23229
23421
|
*
|
|
23230
|
-
*
|
|
23231
|
-
*
|
|
23232
|
-
*
|
|
23233
|
-
*/
|
|
23234
|
-
function atelierPremierePlaceLibre(items, w, h) {
|
|
23235
|
-
const large = borne(w, 1, ATELIER_COLONNES);
|
|
23236
|
-
const haut = borne(h, ATELIER_BORNES.hMin, ATELIER_BORNES.hMax);
|
|
23237
|
-
const carte = occupation(items);
|
|
23238
|
-
for (let y = 0; y <= ATELIER_BORNES.yMax; y++) {
|
|
23239
|
-
for (let x = 0; x + large <= ATELIER_COLONNES; x++) {
|
|
23240
|
-
let libre = true;
|
|
23241
|
-
for (let dy = 0; dy < haut && libre; dy++) {
|
|
23242
|
-
const ligne = carte.get(y + dy);
|
|
23243
|
-
if (!ligne)
|
|
23244
|
-
continue; // ligne entièrement vide
|
|
23245
|
-
for (let dx = 0; dx < large; dx++) {
|
|
23246
|
-
if (ligne[x + dx]) {
|
|
23247
|
-
libre = false;
|
|
23248
|
-
break;
|
|
23249
|
-
}
|
|
23250
|
-
}
|
|
23251
|
-
}
|
|
23252
|
-
if (libre)
|
|
23253
|
-
return { x, y };
|
|
23254
|
-
}
|
|
23255
|
-
}
|
|
23256
|
-
// Plan saturé : on pose en bas plutôt que de refuser. Un outil de maquette ne dit pas non.
|
|
23257
|
-
return { x: 0, y: ATELIER_BORNES.yMax };
|
|
23258
|
-
}
|
|
23259
|
-
/** Nombre TOTAL de composants, enfants compris — c'est lui que borne `itemsMax`. */
|
|
23260
|
-
function atelierCompter(layout) {
|
|
23261
|
-
return layout.items.reduce((n, it) => n + 1 + (it.children?.length ?? 0), 0);
|
|
23262
|
-
}
|
|
23263
|
-
/**
|
|
23264
|
-
* Retrouve un composant OÙ QU'IL VIVE — au premier niveau ou dans un conteneur.
|
|
23265
|
-
* `parentId` dit d'où il vient : c'est ce qui permet à l'inspecteur de remonter.
|
|
23266
|
-
*/
|
|
23267
|
-
function atelierTrouver(layout, id) {
|
|
23268
|
-
for (const it of layout.items) {
|
|
23269
|
-
if (it.id === id)
|
|
23270
|
-
return { item: it, parentId: null };
|
|
23271
|
-
for (const enfant of it.children ?? []) {
|
|
23272
|
-
if (enfant.id === id)
|
|
23273
|
-
return { item: enfant, parentId: it.id };
|
|
23274
|
-
}
|
|
23275
|
-
}
|
|
23276
|
-
return null;
|
|
23277
|
-
}
|
|
23278
|
-
/**
|
|
23279
|
-
* Pose un composant — sur le plan, ou DANS un conteneur (`dansId`).
|
|
23422
|
+
* `<ng-content>` est donc NÉCESSAIRE mais PAS SUFFISANT pour qu'une famille soit un
|
|
23423
|
+
* conteneur d'atelier. Le raccourci « ça projette, donc ça marche » a coûté une matinée :
|
|
23424
|
+
* il faut aussi que l'hôte sache ACCUEILLIR une pièce qu'aucune requête ne lui rapportera.
|
|
23280
23425
|
*
|
|
23281
|
-
*
|
|
23282
|
-
*
|
|
23283
|
-
*
|
|
23284
|
-
*
|
|
23285
|
-
|
|
23286
|
-
|
|
23287
|
-
|
|
23288
|
-
|
|
23289
|
-
// Plafond de l'assainisseur : au-delà, le backend tronquerait EN SILENCE et
|
|
23290
|
-
// l'utilisateur perdrait des composants sans le savoir. On refuse visiblement.
|
|
23291
|
-
return { layout: base, id: '' };
|
|
23292
|
-
}
|
|
23293
|
-
if (dansId) {
|
|
23294
|
-
const cible = atelierTrouver(base, dansId);
|
|
23295
|
-
if (!cible || cible.parentId !== null)
|
|
23296
|
-
return { layout: base, id: '' };
|
|
23297
|
-
if ((cible.item.children?.length ?? 0) >= ATELIER_BORNES.enfantsMax)
|
|
23298
|
-
return { layout: base, id: '' };
|
|
23299
|
-
const id = atelierNouvelId();
|
|
23300
|
-
// `w` d'un enfant = LARGEUR EN COLONNES du conteneur (grille de flux). Il naît
|
|
23301
|
-
// pleine ligne — prévisible — et se réduit ensuite au curseur, comme un bloc.
|
|
23302
|
-
const enfant = { id, type, x: 0, y: 0, w: ATELIER_COLONNES, h: 1 };
|
|
23303
|
-
if (gabarit.props && Object.keys(gabarit.props).length)
|
|
23304
|
-
enfant.props = { ...gabarit.props };
|
|
23305
|
-
return {
|
|
23306
|
-
layout: {
|
|
23307
|
-
version: 1,
|
|
23308
|
-
items: base.items.map((it) => it.id === dansId ? { ...it, children: [...(it.children ?? []), enfant] } : it),
|
|
23309
|
-
},
|
|
23310
|
-
id,
|
|
23311
|
-
};
|
|
23312
|
-
}
|
|
23313
|
-
const w = borne(gabarit.w ?? 4, 1, ATELIER_COLONNES);
|
|
23314
|
-
const h = borne(gabarit.h ?? 2, ATELIER_BORNES.hMin, ATELIER_BORNES.hMax);
|
|
23315
|
-
const { x, y } = atelierPremierePlaceLibre(base.items, w, h);
|
|
23316
|
-
const id = atelierNouvelId();
|
|
23317
|
-
const item = { id, type, x, y, w, h };
|
|
23318
|
-
if (gabarit.props && Object.keys(gabarit.props).length)
|
|
23319
|
-
item.props = { ...gabarit.props };
|
|
23320
|
-
return { layout: { version: 1, items: [...base.items, item] }, id };
|
|
23321
|
-
}
|
|
23322
|
-
/** Retire un composant, où qu'il vive. Retirer un conteneur emporte ses enfants. */
|
|
23323
|
-
function atelierRetirer(layout, id) {
|
|
23324
|
-
return {
|
|
23325
|
-
version: 1,
|
|
23326
|
-
items: layout.items
|
|
23327
|
-
.filter((it) => it.id !== id)
|
|
23328
|
-
.map((it) => {
|
|
23329
|
-
if (!it.children?.some((e) => e.id === id))
|
|
23330
|
-
return it;
|
|
23331
|
-
const enfants = it.children.filter((e) => e.id !== id);
|
|
23332
|
-
const suite = { ...it };
|
|
23333
|
-
if (enfants.length)
|
|
23334
|
-
suite.children = enfants;
|
|
23335
|
-
else
|
|
23336
|
-
delete suite.children;
|
|
23337
|
-
return suite;
|
|
23338
|
-
}),
|
|
23339
|
-
};
|
|
23340
|
-
}
|
|
23341
|
-
/** Change une propriété — où que vive le composant. `undefined` la supprime. */
|
|
23342
|
-
function atelierDefinirProp(layout, id, nom, valeur) {
|
|
23343
|
-
const poserProp = (it) => {
|
|
23344
|
-
const props = { ...(it.props ?? {}) };
|
|
23345
|
-
if (valeur === undefined)
|
|
23346
|
-
delete props[nom];
|
|
23347
|
-
else
|
|
23348
|
-
props[nom] = valeur;
|
|
23349
|
-
const suite = { ...it };
|
|
23350
|
-
if (Object.keys(props).length)
|
|
23351
|
-
suite.props = props;
|
|
23352
|
-
else
|
|
23353
|
-
delete suite.props;
|
|
23354
|
-
return suite;
|
|
23355
|
-
};
|
|
23356
|
-
return {
|
|
23357
|
-
version: 1,
|
|
23358
|
-
items: layout.items.map((it) => {
|
|
23359
|
-
if (it.id === id)
|
|
23360
|
-
return poserProp(it);
|
|
23361
|
-
if (!it.children?.some((e) => e.id === id))
|
|
23362
|
-
return it;
|
|
23363
|
-
return { ...it, children: it.children.map((e) => (e.id === id ? poserProp(e) : e)) };
|
|
23364
|
-
}),
|
|
23365
|
-
};
|
|
23366
|
-
}
|
|
23367
|
-
/**
|
|
23368
|
-
* Déplace un ENFANT d'un cran dans son conteneur (le flux : l'ordre fait loi).
|
|
23369
|
-
* Même chemin pour la souris et le clavier, comme le reste du modèle.
|
|
23426
|
+
* ── LE CONTRAT ──────────────────────────────────────────────────────────────────
|
|
23427
|
+
*
|
|
23428
|
+
* Il n'est pas neuf : `cad-button-group` le porte depuis le 24/08, posé le jour où l'on
|
|
23429
|
+
* a constaté qu'un groupe était SOURD aux clics de ses boutons posés. Ce fichier ne
|
|
23430
|
+
* l'invente pas, il l'ÉCRIT — jusqu'ici il vivait duck-typé dans le seul poseur du
|
|
23431
|
+
* studio, invisible depuis la bibliothèque, ce qui a permis à `cad-map` de partir avec
|
|
23432
|
+
* un nom à lui (`registerChild`) que personne n'appelle. Deux vocabulaires pour un
|
|
23433
|
+
* besoin, c'est une famille cassée en silence.
|
|
23370
23434
|
*/
|
|
23371
|
-
function atelierReordonnerEnfant(layout, parentId, id, sens) {
|
|
23372
|
-
return {
|
|
23373
|
-
version: 1,
|
|
23374
|
-
items: layout.items.map((it) => {
|
|
23375
|
-
if (it.id !== parentId || !it.children)
|
|
23376
|
-
return it;
|
|
23377
|
-
const i = it.children.findIndex((e) => e.id === id);
|
|
23378
|
-
const j = i + sens;
|
|
23379
|
-
if (i < 0 || j < 0 || j >= it.children.length)
|
|
23380
|
-
return it;
|
|
23381
|
-
const enfants = [...it.children];
|
|
23382
|
-
[enfants[i], enfants[j]] = [enfants[j], enfants[i]];
|
|
23383
|
-
return { ...it, children: enfants };
|
|
23384
|
-
}),
|
|
23385
|
-
};
|
|
23386
|
-
}
|
|
23387
23435
|
/**
|
|
23388
|
-
*
|
|
23436
|
+
* L'hôte sait-il accueillir des pièces posées ?
|
|
23389
23437
|
*
|
|
23390
|
-
*
|
|
23391
|
-
*
|
|
23392
|
-
*
|
|
23438
|
+
* Reconnaissance par CAPACITÉ et non par liste de types : un poseur qui énumérerait les
|
|
23439
|
+
* familles concernées serait à mettre à jour à chaque nouvelle — et c'est toujours la
|
|
23440
|
+
* mise à jour qu'on oublie. Une famille qui gagne la trappe devient utilisable dans
|
|
23441
|
+
* l'atelier sans qu'aucun poseur ne bouge.
|
|
23393
23442
|
*/
|
|
23394
|
-
function
|
|
23395
|
-
|
|
23396
|
-
return {
|
|
23397
|
-
version: 1,
|
|
23398
|
-
items: layout.items.map((it) => {
|
|
23399
|
-
if (it.id === id)
|
|
23400
|
-
return { ...it, w: large, x: Math.min(it.x, ATELIER_COLONNES - large) };
|
|
23401
|
-
// Un ENFANT se redimensionne aussi (SZU 24/08 : « on ne peut plus les
|
|
23402
|
-
// redimensionner, très limitatif ») — son `w` est un span de la grille de flux
|
|
23403
|
-
// du conteneur, x reste 0 : pas de placement absolu à l'intérieur.
|
|
23404
|
-
if (!it.children?.some((e) => e.id === id))
|
|
23405
|
-
return it;
|
|
23406
|
-
return {
|
|
23407
|
-
...it,
|
|
23408
|
-
children: it.children.map((e) => (e.id === id ? { ...e, w: large } : e)),
|
|
23409
|
-
};
|
|
23410
|
-
}),
|
|
23411
|
-
};
|
|
23443
|
+
function estHoteAPieces(hote) {
|
|
23444
|
+
return !!hote && typeof hote.enregistrerEnfants === 'function';
|
|
23412
23445
|
}
|
|
23446
|
+
|
|
23413
23447
|
/**
|
|
23414
|
-
*
|
|
23415
|
-
*
|
|
23416
|
-
* C'est le CHEMIN CLAVIER, et il passe par les mêmes fonctions que le glisser — la règle
|
|
23417
|
-
* déjà tenue par `cad-taskboard` et `cad-calendar`. Deux chemins séparés divergent
|
|
23418
|
-
* toujours, et c'est celui du clavier qui pourrit, parce que personne ne le regarde.
|
|
23419
|
-
*/
|
|
23420
|
-
function atelierDeplacer(layout, id, sens) {
|
|
23421
|
-
const ordonne = [...layout.items].sort((a, b) => a.y - b.y || a.x - b.x);
|
|
23422
|
-
const i = ordonne.findIndex((it) => it.id === id);
|
|
23423
|
-
if (i < 0)
|
|
23424
|
-
return layout;
|
|
23425
|
-
const j = i + sens;
|
|
23426
|
-
if (j < 0 || j >= ordonne.length)
|
|
23427
|
-
return layout;
|
|
23428
|
-
[ordonne[i], ordonne[j]] = [ordonne[j], ordonne[i]];
|
|
23429
|
-
// `atelierPoser` et NON `atelierRecompacter` : ce dernier re-trie par (y, x), ce qui
|
|
23430
|
-
// annulerait l'échange qu'on vient de faire — les `y` n'ont pas encore bougé. Défaut
|
|
23431
|
-
// trouvé par le test du clavier, qui rendait le déplacement parfaitement inopérant.
|
|
23432
|
-
return atelierPoser(ordonne);
|
|
23433
|
-
}
|
|
23434
|
-
/**
|
|
23435
|
-
* Repose tous les blocs dans l'ordre de lecture, en supprimant les trous verticaux.
|
|
23436
|
-
*
|
|
23437
|
-
* Le plan garde des positions ABSOLUES (c'est le contrat de frontless), mais une maquette
|
|
23438
|
-
* criblée de lignes vides est illisible. On recompacte donc à chaque réarrangement, en
|
|
23439
|
-
* respectant l'ordre voulu et les largeurs.
|
|
23440
|
-
*/
|
|
23441
|
-
function atelierRecompacter(layout) {
|
|
23442
|
-
return atelierPoser([...layout.items].sort((a, b) => a.y - b.y || a.x - b.x));
|
|
23443
|
-
}
|
|
23444
|
-
/**
|
|
23445
|
-
* Repose les blocs DANS L'ORDRE DU TABLEAU REÇU, sans le retrier.
|
|
23446
|
-
*
|
|
23447
|
-
* La distinction avec `atelierRecompacter` n'est pas cosmétique : après un déplacement au
|
|
23448
|
-
* clavier, l'ordre voulu est celui du tableau, et les `y` portent encore les anciennes
|
|
23449
|
-
* positions. Retrier à ce moment-là annule l'échange — le déplacement devenait
|
|
23450
|
-
* silencieusement inopérant, et c'est le test du clavier qui l'a montré.
|
|
23451
|
-
*/
|
|
23452
|
-
function atelierPoser(items) {
|
|
23453
|
-
const poses = [];
|
|
23454
|
-
for (const it of items) {
|
|
23455
|
-
const { x, y } = atelierPremierePlaceLibre(poses, it.w, it.h);
|
|
23456
|
-
poses.push({ ...it, x, y });
|
|
23457
|
-
}
|
|
23458
|
-
return { version: 1, items: poses };
|
|
23459
|
-
}
|
|
23460
|
-
/**
|
|
23461
|
-
* Ramène un plan venu de l'extérieur dans les clous — un lien partagé, un fichier collé.
|
|
23462
|
-
*
|
|
23463
|
-
* Écarte ce qui est irrécupérable plutôt que de le réparer au jugé : un bloc dont on a
|
|
23464
|
-
* deviné le type serait pire qu'un bloc absent. Même doctrine que l'assainisseur backend,
|
|
23465
|
-
* dont ce n'est PAS un doublon : celui-ci protège l'affichage, celui-là protège la base.
|
|
23466
|
-
*/
|
|
23467
|
-
function atelierNormaliser(brut) {
|
|
23468
|
-
const entree = brut;
|
|
23469
|
-
if (!entree || !Array.isArray(entree.items))
|
|
23470
|
-
return atelierLayoutVide();
|
|
23471
|
-
let total = 0;
|
|
23472
|
-
/**
|
|
23473
|
-
* Un item ramené dans les clous, ou `null` s'il est irrécupérable.
|
|
23474
|
-
* `enfant` change les règles : positions forcées au FLUX (0/0/12/1) et JAMAIS de
|
|
23475
|
-
* petits-enfants — un seul niveau en v1, le surplus est écarté, pas réparé.
|
|
23476
|
-
*/
|
|
23477
|
-
const normaliserItem = (it, enfant) => {
|
|
23478
|
-
if (!it || typeof it !== 'object')
|
|
23479
|
-
return null;
|
|
23480
|
-
const brutItem = it;
|
|
23481
|
-
const type = String(brutItem.type ?? '');
|
|
23482
|
-
if (!/^(?:app:)?[a-z][a-z0-9-]{0,40}$/.test(type))
|
|
23483
|
-
return null;
|
|
23484
|
-
// `w` d'un enfant = span de la grille de flux, GARDÉ (borné 1–12) ; x/y/h forcés.
|
|
23485
|
-
const w = borne(brutItem.w, 1, ATELIER_COLONNES);
|
|
23486
|
-
const x = enfant ? 0 : borne(brutItem.x, 0, ATELIER_COLONNES - w);
|
|
23487
|
-
const h = enfant ? 1 : borne(brutItem.h, ATELIER_BORNES.hMin, ATELIER_BORNES.hMax);
|
|
23488
|
-
const y = enfant ? 0 : borne(brutItem.y, 0, ATELIER_BORNES.yMax);
|
|
23489
|
-
const propre = { id: brutItem.id || atelierNouvelId(), type, x, y, w, h };
|
|
23490
|
-
const props = brutItem.props;
|
|
23491
|
-
if (props && typeof props === 'object' && !Array.isArray(props)) {
|
|
23492
|
-
const gardees = {};
|
|
23493
|
-
for (const [k, v] of Object.entries(props).slice(0, ATELIER_BORNES.propsMax)) {
|
|
23494
|
-
if (!/^[A-Za-z_][A-Za-z0-9_]{0,30}$/.test(k))
|
|
23495
|
-
continue;
|
|
23496
|
-
if (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean')
|
|
23497
|
-
gardees[k] = v;
|
|
23498
|
-
else if (Array.isArray(v))
|
|
23499
|
-
gardees[k] = v.slice(0, 100).map((s) => String(s));
|
|
23500
|
-
}
|
|
23501
|
-
if (Object.keys(gardees).length)
|
|
23502
|
-
propre.props = gardees;
|
|
23503
|
-
}
|
|
23504
|
-
if (brutItem.hideMobile === true)
|
|
23505
|
-
propre.hideMobile = true;
|
|
23506
|
-
if (!enfant && Array.isArray(brutItem.children)) {
|
|
23507
|
-
const enfants = [];
|
|
23508
|
-
for (const e of brutItem.children.slice(0, ATELIER_BORNES.enfantsMax)) {
|
|
23509
|
-
if (total >= ATELIER_BORNES.itemsMax)
|
|
23510
|
-
break;
|
|
23511
|
-
const propreEnfant = normaliserItem(e, true);
|
|
23512
|
-
if (propreEnfant) {
|
|
23513
|
-
enfants.push(propreEnfant);
|
|
23514
|
-
total += 1;
|
|
23515
|
-
}
|
|
23516
|
-
}
|
|
23517
|
-
if (enfants.length)
|
|
23518
|
-
propre.children = enfants;
|
|
23519
|
-
}
|
|
23520
|
-
return propre;
|
|
23521
|
-
};
|
|
23522
|
-
const items = [];
|
|
23523
|
-
for (const it of entree.items) {
|
|
23524
|
-
if (total >= ATELIER_BORNES.itemsMax)
|
|
23525
|
-
break;
|
|
23526
|
-
total += 1; // l'item lui-même, compté AVANT ses enfants pour que le plafond soit global
|
|
23527
|
-
const propre = normaliserItem(it, false);
|
|
23528
|
-
if (propre)
|
|
23529
|
-
items.push(propre);
|
|
23530
|
-
else
|
|
23531
|
-
total -= 1;
|
|
23532
|
-
}
|
|
23533
|
-
return { version: 1, items };
|
|
23534
|
-
}
|
|
23535
|
-
|
|
23536
|
-
/**
|
|
23537
|
-
* Le catalogue de la bibliothèque — GÉNÉRÉ, ne pas modifier à la main.
|
|
23448
|
+
* Le catalogue de la bibliothèque — GÉNÉRÉ, ne pas modifier à la main.
|
|
23538
23449
|
*
|
|
23539
23450
|
* Source : tools/gen-catalog.mjs. Jumeau TypeScript de projects/ui/catalog.json, pour
|
|
23540
23451
|
* les modules de la bibliothèque : ng-packagr ne sait pas résoudre un import JSON hors
|
|
@@ -25827,7 +25738,9 @@ const CATALOGUE = {
|
|
|
25827
25738
|
"ajustement": "naturel",
|
|
25828
25739
|
"icone": "users",
|
|
25829
25740
|
"largeur": "2",
|
|
25830
|
-
"hauteur": "1"
|
|
25741
|
+
"hauteur": "1",
|
|
25742
|
+
"conteneur": "direct",
|
|
25743
|
+
"accepte": "cad-avatar"
|
|
25831
25744
|
},
|
|
25832
25745
|
"inputs": [
|
|
25833
25746
|
{
|
|
@@ -28402,7 +28315,10 @@ const CATALOGUE = {
|
|
|
28402
28315
|
"kind": "component",
|
|
28403
28316
|
"role": null,
|
|
28404
28317
|
"atelier": {
|
|
28405
|
-
"icone": "grid"
|
|
28318
|
+
"icone": "grid",
|
|
28319
|
+
"conteneur": "direct",
|
|
28320
|
+
"largeur": "12",
|
|
28321
|
+
"hauteur": "4"
|
|
28406
28322
|
},
|
|
28407
28323
|
"inputs": [
|
|
28408
28324
|
{
|
|
@@ -28620,7 +28536,8 @@ const CATALOGUE = {
|
|
|
28620
28536
|
"kind": "component",
|
|
28621
28537
|
"role": null,
|
|
28622
28538
|
"atelier": {
|
|
28623
|
-
"icone": "move-horizontal"
|
|
28539
|
+
"icone": "move-horizontal",
|
|
28540
|
+
"surface": "aucune"
|
|
28624
28541
|
},
|
|
28625
28542
|
"inputs": [
|
|
28626
28543
|
{
|
|
@@ -28643,6 +28560,11 @@ const CATALOGUE = {
|
|
|
28643
28560
|
"selector": "cad-splitter-panel",
|
|
28644
28561
|
"kind": "component",
|
|
28645
28562
|
"role": null,
|
|
28563
|
+
"atelier": {
|
|
28564
|
+
"icone": "square",
|
|
28565
|
+
"conteneur": "flux",
|
|
28566
|
+
"dans": "cad-splitter"
|
|
28567
|
+
},
|
|
28646
28568
|
"inputs": [
|
|
28647
28569
|
{
|
|
28648
28570
|
"name": "size",
|
|
@@ -28664,7 +28586,10 @@ const CATALOGUE = {
|
|
|
28664
28586
|
"kind": "component",
|
|
28665
28587
|
"role": null,
|
|
28666
28588
|
"atelier": {
|
|
28667
|
-
"icone": "columns"
|
|
28589
|
+
"icone": "columns",
|
|
28590
|
+
"conteneur": "direct",
|
|
28591
|
+
"largeur": "12",
|
|
28592
|
+
"hauteur": "8"
|
|
28668
28593
|
},
|
|
28669
28594
|
"inputs": [
|
|
28670
28595
|
{
|
|
@@ -30500,6 +30425,12 @@ const CATALOGUE = {
|
|
|
30500
30425
|
"selector": "cad-accordion-panel",
|
|
30501
30426
|
"kind": "component",
|
|
30502
30427
|
"role": null,
|
|
30428
|
+
"atelier": {
|
|
30429
|
+
"icone": "panel-top",
|
|
30430
|
+
"conteneur": "flux",
|
|
30431
|
+
"dans": "cad-accordion",
|
|
30432
|
+
"pose-header": "Section"
|
|
30433
|
+
},
|
|
30503
30434
|
"inputs": [
|
|
30504
30435
|
{
|
|
30505
30436
|
"name": "value",
|
|
@@ -30548,7 +30479,10 @@ const CATALOGUE = {
|
|
|
30548
30479
|
"kind": "component",
|
|
30549
30480
|
"role": null,
|
|
30550
30481
|
"atelier": {
|
|
30551
|
-
"icone": "chevron-down"
|
|
30482
|
+
"icone": "chevron-down",
|
|
30483
|
+
"conteneur": "direct",
|
|
30484
|
+
"largeur": "12",
|
|
30485
|
+
"hauteur": "8"
|
|
30552
30486
|
},
|
|
30553
30487
|
"inputs": [
|
|
30554
30488
|
{
|
|
@@ -31417,6 +31351,12 @@ const CATALOGUE = {
|
|
|
31417
31351
|
"selector": "cad-tab",
|
|
31418
31352
|
"kind": "component",
|
|
31419
31353
|
"role": null,
|
|
31354
|
+
"atelier": {
|
|
31355
|
+
"icone": "panel-top",
|
|
31356
|
+
"conteneur": "flux",
|
|
31357
|
+
"dans": "cad-tabs",
|
|
31358
|
+
"pose-label": "Onglet"
|
|
31359
|
+
},
|
|
31420
31360
|
"inputs": [
|
|
31421
31361
|
{
|
|
31422
31362
|
"name": "value",
|
|
@@ -31466,7 +31406,10 @@ const CATALOGUE = {
|
|
|
31466
31406
|
"kind": "component",
|
|
31467
31407
|
"role": null,
|
|
31468
31408
|
"atelier": {
|
|
31469
|
-
"icone": "folder"
|
|
31409
|
+
"icone": "folder",
|
|
31410
|
+
"conteneur": "direct",
|
|
31411
|
+
"largeur": "12",
|
|
31412
|
+
"hauteur": "6"
|
|
31470
31413
|
},
|
|
31471
31414
|
"inputs": [
|
|
31472
31415
|
{
|
|
@@ -33886,7 +33829,9 @@ const CATALOGUE = {
|
|
|
33886
33829
|
"role": null,
|
|
33887
33830
|
"atelier": {
|
|
33888
33831
|
"icone": "circle-dot",
|
|
33889
|
-
"largeur": "2"
|
|
33832
|
+
"largeur": "2",
|
|
33833
|
+
"conteneur": "direct",
|
|
33834
|
+
"hauteur": "4"
|
|
33890
33835
|
},
|
|
33891
33836
|
"inputs": [
|
|
33892
33837
|
{
|
|
@@ -33930,10 +33875,16 @@ const CATALOGUE = {
|
|
|
33930
33875
|
"selector": "cad-radio",
|
|
33931
33876
|
"kind": "component",
|
|
33932
33877
|
"role": null,
|
|
33878
|
+
"atelier": {
|
|
33879
|
+
"icone": "circle-dot",
|
|
33880
|
+
"conteneur": "flux",
|
|
33881
|
+
"dans": "cad-radio-group",
|
|
33882
|
+
"pose-label": "Option"
|
|
33883
|
+
},
|
|
33933
33884
|
"inputs": [
|
|
33934
33885
|
{
|
|
33935
33886
|
"name": "value",
|
|
33936
|
-
"required":
|
|
33887
|
+
"required": false,
|
|
33937
33888
|
"type": "T"
|
|
33938
33889
|
},
|
|
33939
33890
|
{
|
|
@@ -34244,7 +34195,7 @@ const CATALOGUE = {
|
|
|
34244
34195
|
* Les 61 directives de la bibliothèque n'y figurent pas : une directive ne s'instancie
|
|
34245
34196
|
* pas seule, elle se pose sur un hôte existant. Elles restent visibles dans catalog.json.
|
|
34246
34197
|
*/
|
|
34247
|
-
/** Symbole -> de quoi le construire.
|
|
34198
|
+
/** Symbole -> de quoi le construire. 106 composants posables. */
|
|
34248
34199
|
const REGISTRE = {
|
|
34249
34200
|
CadButtonGroupComponent: { classe: CadButtonGroupComponent, selecteur: "cad-button-group", hote: "cad-button-group" },
|
|
34250
34201
|
CadButtonComponent: { classe: CadButtonComponent, selecteur: "button[cadButton], a[cadButton]", hote: "button" },
|
|
@@ -34316,6 +34267,7 @@ const REGISTRE = {
|
|
|
34316
34267
|
CadMapPanelComponent: { classe: CadMapPanelComponent, selecteur: "cad-map-panel", hote: "cad-map-panel" },
|
|
34317
34268
|
CadMapSectionComponent: { classe: CadMapSectionComponent, selecteur: "cad-map-section", hote: "cad-map-section" },
|
|
34318
34269
|
CadMapComponent: { classe: CadMapComponent, selecteur: "cad-map", hote: "cad-map" },
|
|
34270
|
+
CadAccordionPanelComponent: { classe: CadAccordionPanelComponent, selecteur: "cad-accordion-panel", hote: "cad-accordion-panel" },
|
|
34319
34271
|
CadAccordionComponent: { classe: CadAccordionComponent, selecteur: "cad-accordion", hote: "cad-accordion" },
|
|
34320
34272
|
CadBottomNavComponent: { classe: CadBottomNavComponent, selecteur: "cad-bottom-nav", hote: "cad-bottom-nav" },
|
|
34321
34273
|
CadBreadcrumbComponent: { classe: CadBreadcrumbComponent, selecteur: "cad-breadcrumb", hote: "cad-breadcrumb" },
|
|
@@ -34347,6 +34299,7 @@ const REGISTRE = {
|
|
|
34347
34299
|
CadTreeselectComponent: { classe: CadTreeselectComponent, selecteur: "cad-treeselect", hote: "cad-treeselect" },
|
|
34348
34300
|
CadCheckboxComponent: { classe: CadCheckboxComponent, selecteur: "cad-checkbox", hote: "cad-checkbox" },
|
|
34349
34301
|
CadRadioGroupComponent: { classe: CadRadioGroupComponent, selecteur: "cad-radio-group", hote: "cad-radio-group" },
|
|
34302
|
+
CadRadioComponent: { classe: CadRadioComponent, selecteur: "cad-radio", hote: "cad-radio" },
|
|
34350
34303
|
CadSegmentedComponent: { classe: CadSegmentedComponent, selecteur: "cad-segmented", hote: "cad-segmented" },
|
|
34351
34304
|
CadSwitchComponent: { classe: CadSwitchComponent, selecteur: "cad-switch", hote: "cad-switch" },
|
|
34352
34305
|
CadToggleButtonComponent: { classe: CadToggleButtonComponent, selecteur: "cad-toggle-button", hote: "cad-toggle-button" },
|
|
@@ -34515,9 +34468,11 @@ function construire() {
|
|
|
34515
34468
|
largeur: entierAnnote(meta['largeur'], 1, 12) ?? largeur,
|
|
34516
34469
|
hauteur: entierAnnote(meta['hauteur'], 1, 24) ?? hauteur,
|
|
34517
34470
|
ajustement: meta['ajustement'] === 'naturel' ? 'naturel' : 'remplir',
|
|
34471
|
+
surface: meta['surface'] === 'aucune' ? 'aucune' : 'propre',
|
|
34518
34472
|
rang: entierAnnote(meta['rang'], 1, 99) ?? 99,
|
|
34519
34473
|
exemples: s.exemples ?? {},
|
|
34520
34474
|
dans: meta['dans'] || null,
|
|
34475
|
+
accepte: meta['accepte'] ? meta['accepte'].split('|').filter(Boolean) : null,
|
|
34521
34476
|
icone: meta['icone'] && CAD_ICONS[meta['icone']] ? meta['icone'] : null,
|
|
34522
34477
|
contenu: meta['contenu'] || null,
|
|
34523
34478
|
conteneur,
|
|
@@ -34545,6 +34500,16 @@ function construire() {
|
|
|
34545
34500
|
}
|
|
34546
34501
|
let _palette = null;
|
|
34547
34502
|
let _parCle = null;
|
|
34503
|
+
/**
|
|
34504
|
+
* Les hôtes qui ont AU MOINS UNE pièce, c'est-à-dire les clés citées par un `dans=`.
|
|
34505
|
+
*
|
|
34506
|
+
* C'est la moitié qui manquait. `dans=` était lu dans un seul sens — « cette pièce ne
|
|
34507
|
+
* s'affiche que chez son hôte » — et rien ne disait l'inverse. Un `cad-spacer` entrait
|
|
34508
|
+
* donc dans un `cad-tabs` (constaté au clic par SZU le 27/08) : il partait en base,
|
|
34509
|
+
* s'affichait dans l'inspecteur, et ne rendait rien, puisque l'hôte filtre ses pièces
|
|
34510
|
+
* par type. Le pire des conteneurs : celui qui a l'air d'accepter.
|
|
34511
|
+
*/
|
|
34512
|
+
let _hotesAPieces = null;
|
|
34548
34513
|
/**
|
|
34549
34514
|
* Tous les composants posables — calculés à la PREMIÈRE DEMANDE, jamais au chargement.
|
|
34550
34515
|
*
|
|
@@ -34565,6 +34530,7 @@ function atelierPalette() {
|
|
|
34565
34530
|
if (!_palette) {
|
|
34566
34531
|
_palette = construire();
|
|
34567
34532
|
_parCle = new Map(_palette.map((c) => [c.cle, c]));
|
|
34533
|
+
_hotesAPieces = new Set(_palette.map((c) => c.dans).filter((d) => !!d));
|
|
34568
34534
|
}
|
|
34569
34535
|
return _palette;
|
|
34570
34536
|
}
|
|
@@ -34574,13 +34540,57 @@ function atelierComposant(cle) {
|
|
|
34574
34540
|
return _parCle.get(cle) ?? null;
|
|
34575
34541
|
}
|
|
34576
34542
|
/**
|
|
34577
|
-
*
|
|
34578
|
-
*
|
|
34579
|
-
*
|
|
34580
|
-
*
|
|
34543
|
+
* Cet hôte accepte-t-il ce composant ? `hote = null` désigne le PLAN.
|
|
34544
|
+
*
|
|
34545
|
+
* ⚠️ `dans=` SE LIT DANS LES DEUX SENS, et c'est toute la règle (arbitrage SZU 27/08) :
|
|
34546
|
+
*
|
|
34547
|
+
* · SENS DIRECT — une pièce ne se pose QUE chez son hôte. `cad-map-panel` posé seul
|
|
34548
|
+
* ne montre rien de sensé (signalé le 24/08), `cad-tab` hors d'un `cad-tabs` non plus.
|
|
34549
|
+
* · SENS INVERSE — un hôte QUI A des pièces n'accepte QUE ses pièces. `cad-tabs`
|
|
34550
|
+
* n'accueille que des `cad-tab`, `cad-map` que ses onze pièces de carte.
|
|
34551
|
+
*
|
|
34552
|
+
* La troisième règle en découle sans être écrite : un conteneur SANS pièce déclarée
|
|
34553
|
+
* (`cad-tab`, `cad-panel`, `cad-grid`…) accepte tout, sauf ce qui appartient à un autre
|
|
34554
|
+
* hôte. Rien à annoter : la relation existe déjà, on la lisait à moitié.
|
|
34555
|
+
*/
|
|
34556
|
+
function atelierAccepte(hote, cle) {
|
|
34557
|
+
const c = atelierComposant(cle);
|
|
34558
|
+
if (!c)
|
|
34559
|
+
return false;
|
|
34560
|
+
if (c.dans)
|
|
34561
|
+
return c.dans === hote; // une pièce ne va QUE chez son hôte, jamais au plan
|
|
34562
|
+
if (!hote)
|
|
34563
|
+
return true;
|
|
34564
|
+
const h = atelierComposant(hote);
|
|
34565
|
+
if (h?.accepte)
|
|
34566
|
+
return h.accepte.includes(cle); // strictesse déclarée par l'hôte
|
|
34567
|
+
return !_hotesAPieces.has(hote); // strictesse DÉDUITE : cet hôte a des pièces à lui
|
|
34568
|
+
}
|
|
34569
|
+
/**
|
|
34570
|
+
* Les clés des pièces d'un hôte, dans l'ordre de la palette. Vide si l'hôte n'est pas
|
|
34571
|
+
* strict — c'est le test « ce conteneur a-t-il des pièces à lui ? ».
|
|
34572
|
+
*/
|
|
34573
|
+
function atelierPiecesDe(hote) {
|
|
34574
|
+
if (!hote)
|
|
34575
|
+
return [];
|
|
34576
|
+
const h = atelierComposant(hote);
|
|
34577
|
+
if (h?.accepte)
|
|
34578
|
+
return [...h.accepte];
|
|
34579
|
+
return atelierPalette().filter((c) => c.dans === hote).map((c) => c.cle);
|
|
34580
|
+
}
|
|
34581
|
+
/**
|
|
34582
|
+
* Recherche par nom, clé ou sélecteur. Rend TOUT ce qui correspond au terme.
|
|
34583
|
+
*
|
|
34584
|
+
* ⚠️ NE FILTRE PLUS SUR LA CIBLE, et c'est délibéré (SZU 27/08, règle déjà posée le
|
|
34585
|
+
* 26/08 pour le builder) : ce qu'un conteneur refuse doit apparaître VERROUILLÉ, pas
|
|
34586
|
+
* disparaître. Masquer fait deux dégâts — ça dérobe l'information (l'utilisateur ne sait
|
|
34587
|
+
* pas que le composant existe, ni pourquoi il n'est pas là) et ça fait SAUTER la palette
|
|
34588
|
+
* à chaque changement de sélection, si bien qu'on ne retrouve plus rien où on l'avait vu.
|
|
34589
|
+
*
|
|
34590
|
+
* L'appelant interroge `atelierAccepte` pour savoir quoi désactiver, et dit pourquoi.
|
|
34581
34591
|
*/
|
|
34582
|
-
function atelierChercher(terme
|
|
34583
|
-
const visibles = atelierPalette()
|
|
34592
|
+
function atelierChercher(terme) {
|
|
34593
|
+
const visibles = [...atelierPalette()];
|
|
34584
34594
|
const q = terme.trim().toLowerCase();
|
|
34585
34595
|
if (!q)
|
|
34586
34596
|
return visibles;
|
|
@@ -34589,10 +34599,15 @@ function atelierChercher(terme, hote = null) {
|
|
|
34589
34599
|
c.symbole.toLowerCase().includes(q) ||
|
|
34590
34600
|
(c.role ?? '').toLowerCase().includes(q));
|
|
34591
34601
|
}
|
|
34592
|
-
/**
|
|
34593
|
-
|
|
34602
|
+
/**
|
|
34603
|
+
* Les composants groupés, dans l'ordre d'affichage de la palette.
|
|
34604
|
+
*
|
|
34605
|
+
* Les groupes ne dépendent PAS de la cible : la palette garde la même forme quoi qu'on
|
|
34606
|
+
* sélectionne, ce qui est la moitié de l'intérêt du verrouillage-expliqué.
|
|
34607
|
+
*/
|
|
34608
|
+
function atelierGroupes(terme = '') {
|
|
34594
34609
|
const par = new Map();
|
|
34595
|
-
for (const c of atelierChercher(terme
|
|
34610
|
+
for (const c of atelierChercher(terme)) {
|
|
34596
34611
|
if (!par.has(c.groupe))
|
|
34597
34612
|
par.set(c.groupe, []);
|
|
34598
34613
|
par.get(c.groupe).push(c);
|
|
@@ -34600,6 +34615,521 @@ function atelierGroupes(terme = '', hote = null) {
|
|
|
34600
34615
|
return [...par.entries()].map(([groupe, composants]) => ({ groupe, composants }));
|
|
34601
34616
|
}
|
|
34602
34617
|
|
|
34618
|
+
/**
|
|
34619
|
+
* Les opérations du plan, en logique PURE — aucun DOM, aucun Angular.
|
|
34620
|
+
*
|
|
34621
|
+
* Même parti que `lib/planning/` : ce qui décide se teste sans rendu. Les défauts du
|
|
34622
|
+
* calendrier ont tous été trouvés là, et deux fois c'est mon ATTENTE de test qui était
|
|
34623
|
+
* fausse, pas le code — c'est plus facile à voir sur une fonction pure.
|
|
34624
|
+
*
|
|
34625
|
+
* Toutes rendent un NOUVEAU plan : la maquette est de la donnée, on ne la mute pas sous
|
|
34626
|
+
* les pieds de qui l'affiche.
|
|
34627
|
+
*/
|
|
34628
|
+
/** Compteur de la session : les identifiants n'ont pas à être uniques au monde, seulement dans un plan. */
|
|
34629
|
+
let compteur = 0;
|
|
34630
|
+
/** Identifiant conforme à l'assainisseur backend : `/^[A-Za-z0-9_-]{1,24}$/`. */
|
|
34631
|
+
function atelierNouvelId() {
|
|
34632
|
+
compteur += 1;
|
|
34633
|
+
return `i${compteur.toString(36)}`;
|
|
34634
|
+
}
|
|
34635
|
+
/** Remet le compteur à zéro. Réservé aux tests, pour qu'ils ne dépendent pas de leur ordre. */
|
|
34636
|
+
function atelierReinitialiserIds() {
|
|
34637
|
+
compteur = 0;
|
|
34638
|
+
}
|
|
34639
|
+
/** Fait remonter le compteur au-dessus d'un id existant. Silencieux sur une autre forme. */
|
|
34640
|
+
function adopterId(id) {
|
|
34641
|
+
const m = /^i([0-9a-z]+)$/.exec(id ?? '');
|
|
34642
|
+
if (!m)
|
|
34643
|
+
return;
|
|
34644
|
+
const n = parseInt(m[1], 36);
|
|
34645
|
+
if (Number.isSafeInteger(n) && n > compteur)
|
|
34646
|
+
compteur = n;
|
|
34647
|
+
}
|
|
34648
|
+
/**
|
|
34649
|
+
* Empêche les prochains ids de VOLER l'identité d'items déjà présents.
|
|
34650
|
+
*
|
|
34651
|
+
* ⚠️ À APPELER À CHAQUE CHARGEMENT d'un plan venu d'ailleurs (base, fichier collé). Le
|
|
34652
|
+
* compteur est propre à la SESSION et repart de zéro : une maquette rechargée porte déjà
|
|
34653
|
+
* `i1`, `i2`… et la première pose redonnait `i1`. Deux items partagent alors une clé, et
|
|
34654
|
+
* tout ce qui vise par id se trompe de cible — `atelierTrouver` rend le premier homonyme,
|
|
34655
|
+
* `transformerArbre` édite les deux, et le `@for … track` d'Angular en FUSIONNE deux à
|
|
34656
|
+
* l'écran : un bloc disparaît du canevas sans qu'aucune erreur ne soit levée (NG0955 en
|
|
34657
|
+
* avertissement, c'est tout).
|
|
34658
|
+
*
|
|
34659
|
+
* C'EST LE MÊME DÉFAUT QUE `eb87d3f7` (26/08), qui l'avait corrigé dans le builder
|
|
34660
|
+
* frontless — « le compteur valait items.length et non le plus grand id existant ». Le
|
|
34661
|
+
* format a DEUX producteurs ; le correctif n'en avait couvert qu'un. Il vit désormais
|
|
34662
|
+
* dans la bibliothèque, là où les deux le partagent.
|
|
34663
|
+
*/
|
|
34664
|
+
function atelierAdopterIds(layout) {
|
|
34665
|
+
const parcourir = (items) => {
|
|
34666
|
+
for (const it of items) {
|
|
34667
|
+
adopterId(it.id);
|
|
34668
|
+
parcourir(it.children ?? []);
|
|
34669
|
+
}
|
|
34670
|
+
};
|
|
34671
|
+
parcourir(layout?.items ?? []);
|
|
34672
|
+
}
|
|
34673
|
+
const borne = (v, min, max) => Math.max(min, Math.min(max, Math.trunc(Number.isFinite(v) ? v : min)));
|
|
34674
|
+
/**
|
|
34675
|
+
* La carte d'occupation du plan, ligne par ligne.
|
|
34676
|
+
*
|
|
34677
|
+
* On ne garde pas de largeur fixe : une ligne absente est une ligne vide. Un plan de
|
|
34678
|
+
* trois éléments ne fabrique pas 500 tableaux.
|
|
34679
|
+
*/
|
|
34680
|
+
function occupation(items, sauf) {
|
|
34681
|
+
const lignes = new Map();
|
|
34682
|
+
for (const it of items) {
|
|
34683
|
+
if (sauf && it.id === sauf)
|
|
34684
|
+
continue;
|
|
34685
|
+
for (let y = it.y; y < it.y + it.h; y++) {
|
|
34686
|
+
let ligne = lignes.get(y);
|
|
34687
|
+
if (!ligne) {
|
|
34688
|
+
ligne = new Array(ATELIER_COLONNES).fill(false);
|
|
34689
|
+
lignes.set(y, ligne);
|
|
34690
|
+
}
|
|
34691
|
+
for (let x = it.x; x < it.x + it.w && x < ATELIER_COLONNES; x++)
|
|
34692
|
+
ligne[x] = true;
|
|
34693
|
+
}
|
|
34694
|
+
}
|
|
34695
|
+
return lignes;
|
|
34696
|
+
}
|
|
34697
|
+
/**
|
|
34698
|
+
* La première position libre pour un bloc de `w × h`, en balayant de haut en bas puis de
|
|
34699
|
+
* gauche à droite.
|
|
34700
|
+
*
|
|
34701
|
+
* C'est ce qui rend le CLIC utilisable comme geste principal : on choisit dans la palette
|
|
34702
|
+
* et ça se pose à un endroit sensé, sans viser. Le glisser sert ensuite à réarranger,
|
|
34703
|
+
* là où il est réellement meilleur.
|
|
34704
|
+
*/
|
|
34705
|
+
function atelierPremierePlaceLibre(items, w, h) {
|
|
34706
|
+
const large = borne(w, 1, ATELIER_COLONNES);
|
|
34707
|
+
const haut = borne(h, ATELIER_BORNES.hMin, ATELIER_BORNES.hMax);
|
|
34708
|
+
const carte = occupation(items);
|
|
34709
|
+
for (let y = 0; y <= ATELIER_BORNES.yMax; y++) {
|
|
34710
|
+
for (let x = 0; x + large <= ATELIER_COLONNES; x++) {
|
|
34711
|
+
let libre = true;
|
|
34712
|
+
for (let dy = 0; dy < haut && libre; dy++) {
|
|
34713
|
+
const ligne = carte.get(y + dy);
|
|
34714
|
+
if (!ligne)
|
|
34715
|
+
continue; // ligne entièrement vide
|
|
34716
|
+
for (let dx = 0; dx < large; dx++) {
|
|
34717
|
+
if (ligne[x + dx]) {
|
|
34718
|
+
libre = false;
|
|
34719
|
+
break;
|
|
34720
|
+
}
|
|
34721
|
+
}
|
|
34722
|
+
}
|
|
34723
|
+
if (libre)
|
|
34724
|
+
return { x, y };
|
|
34725
|
+
}
|
|
34726
|
+
}
|
|
34727
|
+
// Plan saturé : on pose en bas plutôt que de refuser. Un outil de maquette ne dit pas non.
|
|
34728
|
+
return { x: 0, y: ATELIER_BORNES.yMax };
|
|
34729
|
+
}
|
|
34730
|
+
/**
|
|
34731
|
+
* Applique une transformation à CHAQUE item de l'arbre, enfants compris.
|
|
34732
|
+
*
|
|
34733
|
+
* Toutes les opérations qui touchent « un composant, où qu'il vive » passent par ici :
|
|
34734
|
+
* retirer, éditer une prop, redimensionner, réordonner. Écrire la descente une seule
|
|
34735
|
+
* fois est ce qui a permis de lever le plafond d'un niveau sans réécrire six fonctions —
|
|
34736
|
+
* et surtout sans en oublier une, ce qui aurait donné un modèle qui pose en profondeur
|
|
34737
|
+
* mais refuse d'y éditer.
|
|
34738
|
+
*
|
|
34739
|
+
* `fn` rend l'item transformé, ou `null` pour l'écarter (ses enfants partent avec lui).
|
|
34740
|
+
* La profondeur est passée parce qu'elle CHANGE les règles : au premier niveau le
|
|
34741
|
+
* placement est absolu, en dessous c'est un flux.
|
|
34742
|
+
*/
|
|
34743
|
+
function transformerArbre(items, fn, profondeur = 0) {
|
|
34744
|
+
const sortie = [];
|
|
34745
|
+
for (const it of items) {
|
|
34746
|
+
const transforme = fn(it, profondeur);
|
|
34747
|
+
if (!transforme)
|
|
34748
|
+
continue;
|
|
34749
|
+
if (!transforme.children) {
|
|
34750
|
+
sortie.push(transforme);
|
|
34751
|
+
continue;
|
|
34752
|
+
}
|
|
34753
|
+
const enfants = transformerArbre(transforme.children, fn, profondeur + 1);
|
|
34754
|
+
const suite = { ...transforme };
|
|
34755
|
+
if (enfants.length)
|
|
34756
|
+
suite.children = enfants;
|
|
34757
|
+
else
|
|
34758
|
+
delete suite.children;
|
|
34759
|
+
sortie.push(suite);
|
|
34760
|
+
}
|
|
34761
|
+
return sortie;
|
|
34762
|
+
}
|
|
34763
|
+
/** Nombre TOTAL de composants, à toutes les profondeurs — c'est lui que borne `itemsMax`. */
|
|
34764
|
+
function atelierCompter(layout) {
|
|
34765
|
+
const compter = (items) => items.reduce((n, it) => n + 1 + compter(it.children ?? []), 0);
|
|
34766
|
+
return compter(layout.items);
|
|
34767
|
+
}
|
|
34768
|
+
/**
|
|
34769
|
+
* Retrouve un composant OÙ QU'IL VIVE, à n'importe quelle profondeur.
|
|
34770
|
+
*
|
|
34771
|
+
* `parentId` dit d'où il vient — c'est ce qui permet à l'inspecteur de remonter, d'un
|
|
34772
|
+
* cran à la fois. `profondeur` dit à quel étage il se trouve (0 = sur le plan) : la
|
|
34773
|
+
* pose s'en sert pour refuser AVANT d'agir, plutôt que de tronquer après.
|
|
34774
|
+
*/
|
|
34775
|
+
function atelierTrouver(layout, id) {
|
|
34776
|
+
const chercher = (items, parentId, profondeur) => {
|
|
34777
|
+
for (const it of items) {
|
|
34778
|
+
if (it.id === id)
|
|
34779
|
+
return { item: it, parentId, profondeur };
|
|
34780
|
+
const dedans = chercher(it.children ?? [], it.id, profondeur + 1);
|
|
34781
|
+
if (dedans)
|
|
34782
|
+
return dedans;
|
|
34783
|
+
}
|
|
34784
|
+
return null;
|
|
34785
|
+
};
|
|
34786
|
+
return chercher(layout.items, null, 0);
|
|
34787
|
+
}
|
|
34788
|
+
/**
|
|
34789
|
+
* Pose un composant — sur le plan, ou DANS un conteneur (`dansId`), à n'importe quelle
|
|
34790
|
+
* profondeur jusqu'à `profondeurMax`.
|
|
34791
|
+
*
|
|
34792
|
+
* Dans un conteneur, l'enfant vit en FLUX : ajouté en fin, x/y/w/h normalisés (0/0/12/1),
|
|
34793
|
+
* l'ordre fait loi. Refus VISIBLE (id vide) si le conteneur n'existe pas, s'il est déjà
|
|
34794
|
+
* au dernier étage autorisé, ou si un plafond est atteint — jamais de troncature
|
|
34795
|
+
* silencieuse, même doctrine que le plafond global.
|
|
34796
|
+
*/
|
|
34797
|
+
function atelierAjouter(layout, type, gabarit = {}, dansId) {
|
|
34798
|
+
const base = layout ?? atelierLayoutVide();
|
|
34799
|
+
if (atelierCompter(base) >= ATELIER_BORNES.itemsMax) {
|
|
34800
|
+
// Plafond de l'assainisseur : au-delà, le backend tronquerait EN SILENCE et
|
|
34801
|
+
// l'utilisateur perdrait des composants sans le savoir. On refuse visiblement.
|
|
34802
|
+
return { layout: base, id: '' };
|
|
34803
|
+
}
|
|
34804
|
+
if (dansId) {
|
|
34805
|
+
const cible = atelierTrouver(base, dansId);
|
|
34806
|
+
if (!cible)
|
|
34807
|
+
return { layout: base, id: '' };
|
|
34808
|
+
// UN HÔTE N'ACCEPTE PAS TOUT (SZU 27/08) : `cad-tabs` n'accueille que des `cad-tab`,
|
|
34809
|
+
// `cad-map` que ses pièces de carte. La palette le montre déjà en verrouillant, mais
|
|
34810
|
+
// elle est de l'affichage ; le modèle est la vérité, et rien d'autre ne protège les
|
|
34811
|
+
// chemins qui ne passent pas par elle (collage, import, appel programmatique). Un
|
|
34812
|
+
// `cad-spacer` glissé dans un `cad-tabs` partait en base et ne rendait jamais rien.
|
|
34813
|
+
if (!atelierAccepte(cible.item.type, type))
|
|
34814
|
+
return { layout: base, id: '' };
|
|
34815
|
+
// L'ENFANT naîtrait un cran plus bas que sa cible : c'est SA profondeur qu'on borne.
|
|
34816
|
+
if (cible.profondeur + 1 > ATELIER_BORNES.profondeurMax)
|
|
34817
|
+
return { layout: base, id: '' };
|
|
34818
|
+
if ((cible.item.children?.length ?? 0) >= ATELIER_BORNES.enfantsMax)
|
|
34819
|
+
return { layout: base, id: '' };
|
|
34820
|
+
const id = atelierNouvelId();
|
|
34821
|
+
// `w` d'un enfant = LARGEUR EN COLONNES du conteneur (grille de flux). Les deux
|
|
34822
|
+
// poseurs en passent une utile (palette 2/12, builder def.w×2) : l'honorer, sinon
|
|
34823
|
+
// l'aperçu et le modèle divergent. Sans gabarit, il naît pleine ligne — prévisible.
|
|
34824
|
+
const enfant = {
|
|
34825
|
+
id, type, x: 0, y: 0,
|
|
34826
|
+
w: borne(gabarit.w ?? ATELIER_COLONNES, 1, ATELIER_COLONNES),
|
|
34827
|
+
h: 1,
|
|
34828
|
+
};
|
|
34829
|
+
if (gabarit.props && Object.keys(gabarit.props).length)
|
|
34830
|
+
enfant.props = { ...gabarit.props };
|
|
34831
|
+
return {
|
|
34832
|
+
layout: {
|
|
34833
|
+
version: 1,
|
|
34834
|
+
items: transformerArbre(base.items, (it) => it.id === dansId ? { ...it, children: [...(it.children ?? []), enfant] } : it),
|
|
34835
|
+
},
|
|
34836
|
+
id,
|
|
34837
|
+
};
|
|
34838
|
+
}
|
|
34839
|
+
const w = borne(gabarit.w ?? 4, 1, ATELIER_COLONNES);
|
|
34840
|
+
const h = borne(gabarit.h ?? 2, ATELIER_BORNES.hMin, ATELIER_BORNES.hMax);
|
|
34841
|
+
const { x, y } = atelierPremierePlaceLibre(base.items, w, h);
|
|
34842
|
+
const id = atelierNouvelId();
|
|
34843
|
+
const item = { id, type, x, y, w, h };
|
|
34844
|
+
if (gabarit.props && Object.keys(gabarit.props).length)
|
|
34845
|
+
item.props = { ...gabarit.props };
|
|
34846
|
+
return { layout: { version: 1, items: [...base.items, item] }, id };
|
|
34847
|
+
}
|
|
34848
|
+
/**
|
|
34849
|
+
* Retire un composant, où qu'il vive et à quelque profondeur que ce soit.
|
|
34850
|
+
* Retirer un conteneur emporte toute sa descendance — jamais d'orphelin invisible.
|
|
34851
|
+
*/
|
|
34852
|
+
function atelierRetirer(layout, id) {
|
|
34853
|
+
return {
|
|
34854
|
+
version: 1,
|
|
34855
|
+
items: transformerArbre(layout.items, (it) => (it.id === id ? null : it)),
|
|
34856
|
+
};
|
|
34857
|
+
}
|
|
34858
|
+
/** Change une propriété — où que vive le composant. `undefined` la supprime. */
|
|
34859
|
+
function atelierDefinirProp(layout, id, nom, valeur) {
|
|
34860
|
+
const poserProp = (it) => {
|
|
34861
|
+
const props = { ...(it.props ?? {}) };
|
|
34862
|
+
if (valeur === undefined)
|
|
34863
|
+
delete props[nom];
|
|
34864
|
+
else
|
|
34865
|
+
props[nom] = valeur;
|
|
34866
|
+
const suite = { ...it };
|
|
34867
|
+
if (Object.keys(props).length)
|
|
34868
|
+
suite.props = props;
|
|
34869
|
+
else
|
|
34870
|
+
delete suite.props;
|
|
34871
|
+
return suite;
|
|
34872
|
+
};
|
|
34873
|
+
return {
|
|
34874
|
+
version: 1,
|
|
34875
|
+
items: transformerArbre(layout.items, (it) => (it.id === id ? poserProp(it) : it)),
|
|
34876
|
+
};
|
|
34877
|
+
}
|
|
34878
|
+
/**
|
|
34879
|
+
* Déplace un ENFANT d'un cran dans son conteneur (le flux : l'ordre fait loi).
|
|
34880
|
+
* Même chemin pour la souris et le clavier, comme le reste du modèle.
|
|
34881
|
+
*/
|
|
34882
|
+
function atelierReordonnerEnfant(layout, parentId, id, sens) {
|
|
34883
|
+
return {
|
|
34884
|
+
version: 1,
|
|
34885
|
+
items: transformerArbre(layout.items, (it) => {
|
|
34886
|
+
if (it.id !== parentId || !it.children)
|
|
34887
|
+
return it;
|
|
34888
|
+
const i = it.children.findIndex((e) => e.id === id);
|
|
34889
|
+
const j = i + sens;
|
|
34890
|
+
if (i < 0 || j < 0 || j >= it.children.length)
|
|
34891
|
+
return it;
|
|
34892
|
+
const enfants = [...it.children];
|
|
34893
|
+
[enfants[i], enfants[j]] = [enfants[j], enfants[i]];
|
|
34894
|
+
return { ...it, children: enfants };
|
|
34895
|
+
}),
|
|
34896
|
+
};
|
|
34897
|
+
}
|
|
34898
|
+
/**
|
|
34899
|
+
* Change la largeur, en gardant le bloc DANS la grille.
|
|
34900
|
+
*
|
|
34901
|
+
* On décale x quand la largeur déborde, plutôt que de rogner w : l'utilisateur a demandé
|
|
34902
|
+
* une largeur, pas une place. Rogner silencieusement donnerait un bloc plus étroit que
|
|
34903
|
+
* ce qu'il a réglé, sans rien dire.
|
|
34904
|
+
*/
|
|
34905
|
+
function atelierRedimensionner(layout, id, w) {
|
|
34906
|
+
const large = borne(w, 1, ATELIER_COLONNES);
|
|
34907
|
+
return {
|
|
34908
|
+
version: 1,
|
|
34909
|
+
items: transformerArbre(layout.items, (it, profondeur) => {
|
|
34910
|
+
if (it.id !== id)
|
|
34911
|
+
return it;
|
|
34912
|
+
// Sur le PLAN, la largeur peut déborder de la grille : on décale x plutôt que de
|
|
34913
|
+
// rogner w. Un ENFANT, lui, se redimensionne aussi (SZU 24/08 : « on ne peut plus
|
|
34914
|
+
// les redimensionner, très limitatif ») mais son `w` est un span de la grille de
|
|
34915
|
+
// flux de son conteneur, x reste 0 : pas de placement absolu à l'intérieur.
|
|
34916
|
+
return profondeur === 0
|
|
34917
|
+
? { ...it, w: large, x: Math.min(it.x, ATELIER_COLONNES - large) }
|
|
34918
|
+
: { ...it, w: large };
|
|
34919
|
+
}),
|
|
34920
|
+
};
|
|
34921
|
+
}
|
|
34922
|
+
/**
|
|
34923
|
+
* Déplace un bloc d'un cran dans l'ordre de lecture (haut/bas), puis recompacte.
|
|
34924
|
+
*
|
|
34925
|
+
* C'est le CHEMIN CLAVIER, et il passe par les mêmes fonctions que le glisser — la règle
|
|
34926
|
+
* déjà tenue par `cad-taskboard` et `cad-calendar`. Deux chemins séparés divergent
|
|
34927
|
+
* toujours, et c'est celui du clavier qui pourrit, parce que personne ne le regarde.
|
|
34928
|
+
*/
|
|
34929
|
+
function atelierDeplacer(layout, id, sens) {
|
|
34930
|
+
const ordonne = [...layout.items].sort((a, b) => a.y - b.y || a.x - b.x);
|
|
34931
|
+
const i = ordonne.findIndex((it) => it.id === id);
|
|
34932
|
+
if (i < 0)
|
|
34933
|
+
return layout;
|
|
34934
|
+
const j = i + sens;
|
|
34935
|
+
if (j < 0 || j >= ordonne.length)
|
|
34936
|
+
return layout;
|
|
34937
|
+
[ordonne[i], ordonne[j]] = [ordonne[j], ordonne[i]];
|
|
34938
|
+
// `atelierPoser` et NON `atelierRecompacter` : ce dernier re-trie par (y, x), ce qui
|
|
34939
|
+
// annulerait l'échange qu'on vient de faire — les `y` n'ont pas encore bougé. Défaut
|
|
34940
|
+
// trouvé par le test du clavier, qui rendait le déplacement parfaitement inopérant.
|
|
34941
|
+
return atelierPoser(ordonne);
|
|
34942
|
+
}
|
|
34943
|
+
/**
|
|
34944
|
+
* Repose tous les blocs dans l'ordre de lecture, en supprimant les trous verticaux.
|
|
34945
|
+
*
|
|
34946
|
+
* Le plan garde des positions ABSOLUES (c'est le contrat de frontless), mais une maquette
|
|
34947
|
+
* criblée de lignes vides est illisible. On recompacte donc à chaque réarrangement, en
|
|
34948
|
+
* respectant l'ordre voulu et les largeurs.
|
|
34949
|
+
*/
|
|
34950
|
+
function atelierRecompacter(layout) {
|
|
34951
|
+
return atelierPoser([...layout.items].sort((a, b) => a.y - b.y || a.x - b.x));
|
|
34952
|
+
}
|
|
34953
|
+
/**
|
|
34954
|
+
* Repose les blocs DANS L'ORDRE DU TABLEAU REÇU, sans le retrier.
|
|
34955
|
+
*
|
|
34956
|
+
* La distinction avec `atelierRecompacter` n'est pas cosmétique : après un déplacement au
|
|
34957
|
+
* clavier, l'ordre voulu est celui du tableau, et les `y` portent encore les anciennes
|
|
34958
|
+
* positions. Retrier à ce moment-là annule l'échange — le déplacement devenait
|
|
34959
|
+
* silencieusement inopérant, et c'est le test du clavier qui l'a montré.
|
|
34960
|
+
*/
|
|
34961
|
+
function atelierPoser(items) {
|
|
34962
|
+
const poses = [];
|
|
34963
|
+
for (const it of items) {
|
|
34964
|
+
const { x, y } = atelierPremierePlaceLibre(poses, it.w, it.h);
|
|
34965
|
+
poses.push({ ...it, x, y });
|
|
34966
|
+
}
|
|
34967
|
+
return { version: 1, items: poses };
|
|
34968
|
+
}
|
|
34969
|
+
/**
|
|
34970
|
+
* Ramène un plan venu de l'extérieur dans les clous — un lien partagé, un fichier collé.
|
|
34971
|
+
*
|
|
34972
|
+
* Écarte ce qui est irrécupérable plutôt que de le réparer au jugé : un bloc dont on a
|
|
34973
|
+
* deviné le type serait pire qu'un bloc absent. Même doctrine que l'assainisseur backend,
|
|
34974
|
+
* dont ce n'est PAS un doublon : celui-ci protège l'affichage, celui-là protège la base.
|
|
34975
|
+
*/
|
|
34976
|
+
function atelierNormaliser(brut) {
|
|
34977
|
+
const entree = brut;
|
|
34978
|
+
if (!entree || !Array.isArray(entree.items))
|
|
34979
|
+
return atelierLayoutVide();
|
|
34980
|
+
let total = 0;
|
|
34981
|
+
/**
|
|
34982
|
+
* Un item ramené dans les clous, ou `null` s'il est irrécupérable.
|
|
34983
|
+
*
|
|
34984
|
+
* La PROFONDEUR change les règles : à 0 le placement est absolu, en dessous il est
|
|
34985
|
+
* forcé au FLUX (x/y/h normalisés, seul `w` — le span — survit). Au-delà de
|
|
34986
|
+
* `profondeurMax` la descendance est écartée, pas réparée : borner ici n'est pas de
|
|
34987
|
+
* l'ergonomie, c'est ce qui empêche un JSON hostile de faire sauter la pile.
|
|
34988
|
+
*/
|
|
34989
|
+
const normaliserItem = (it, profondeur) => {
|
|
34990
|
+
const enfant = profondeur > 0;
|
|
34991
|
+
if (!it || typeof it !== 'object')
|
|
34992
|
+
return null;
|
|
34993
|
+
const brutItem = it;
|
|
34994
|
+
const type = String(brutItem.type ?? '');
|
|
34995
|
+
if (!/^(?:app:)?[a-z][a-z0-9-]{0,40}$/.test(type))
|
|
34996
|
+
return null;
|
|
34997
|
+
// `w` d'un enfant = span de la grille de flux, GARDÉ (borné 1–12) ; x/y/h forcés.
|
|
34998
|
+
const w = borne(brutItem.w, 1, ATELIER_COLONNES);
|
|
34999
|
+
const x = enfant ? 0 : borne(brutItem.x, 0, ATELIER_COLONNES - w);
|
|
35000
|
+
const h = enfant ? 1 : borne(brutItem.h, ATELIER_BORNES.hMin, ATELIER_BORNES.hMax);
|
|
35001
|
+
const y = enfant ? 0 : borne(brutItem.y, 0, ATELIER_BORNES.yMax);
|
|
35002
|
+
adopterId(brutItem.id); // avant de fabriquer quoi que ce soit : pas d'homonyme
|
|
35003
|
+
const propre = { id: brutItem.id || atelierNouvelId(), type, x, y, w, h };
|
|
35004
|
+
const props = brutItem.props;
|
|
35005
|
+
if (props && typeof props === 'object' && !Array.isArray(props)) {
|
|
35006
|
+
const gardees = {};
|
|
35007
|
+
for (const [k, v] of Object.entries(props).slice(0, ATELIER_BORNES.propsMax)) {
|
|
35008
|
+
if (!/^[A-Za-z_][A-Za-z0-9_]{0,30}$/.test(k))
|
|
35009
|
+
continue;
|
|
35010
|
+
if (typeof v === 'string' || typeof v === 'number' || typeof v === 'boolean')
|
|
35011
|
+
gardees[k] = v;
|
|
35012
|
+
else if (Array.isArray(v))
|
|
35013
|
+
gardees[k] = v.slice(0, 100).map((s) => String(s));
|
|
35014
|
+
}
|
|
35015
|
+
if (Object.keys(gardees).length)
|
|
35016
|
+
propre.props = gardees;
|
|
35017
|
+
}
|
|
35018
|
+
if (brutItem.hideMobile === true)
|
|
35019
|
+
propre.hideMobile = true;
|
|
35020
|
+
if (profondeur < ATELIER_BORNES.profondeurMax && Array.isArray(brutItem.children)) {
|
|
35021
|
+
const enfants = [];
|
|
35022
|
+
for (const e of brutItem.children.slice(0, ATELIER_BORNES.enfantsMax)) {
|
|
35023
|
+
if (total >= ATELIER_BORNES.itemsMax)
|
|
35024
|
+
break;
|
|
35025
|
+
total += 1; // compté AVANT sa descendance, pour que le plafond reste global
|
|
35026
|
+
const propreEnfant = normaliserItem(e, profondeur + 1);
|
|
35027
|
+
if (propreEnfant)
|
|
35028
|
+
enfants.push(propreEnfant);
|
|
35029
|
+
else
|
|
35030
|
+
total -= 1;
|
|
35031
|
+
}
|
|
35032
|
+
if (enfants.length)
|
|
35033
|
+
propre.children = enfants;
|
|
35034
|
+
}
|
|
35035
|
+
return propre;
|
|
35036
|
+
};
|
|
35037
|
+
const items = [];
|
|
35038
|
+
for (const it of entree.items) {
|
|
35039
|
+
if (total >= ATELIER_BORNES.itemsMax)
|
|
35040
|
+
break;
|
|
35041
|
+
total += 1; // l'item lui-même, compté AVANT ses enfants pour que le plafond soit global
|
|
35042
|
+
const propre = normaliserItem(it, 0);
|
|
35043
|
+
if (propre)
|
|
35044
|
+
items.push(propre);
|
|
35045
|
+
else
|
|
35046
|
+
total -= 1;
|
|
35047
|
+
}
|
|
35048
|
+
return { version: 1, items };
|
|
35049
|
+
}
|
|
35050
|
+
|
|
35051
|
+
/** Le libellé d'une pièce, pour le chemin : son `label`/`header`, sinon son type. */
|
|
35052
|
+
function libelle(props, type) {
|
|
35053
|
+
for (const k of ['label', 'header', 'title']) {
|
|
35054
|
+
const v = props?.[k];
|
|
35055
|
+
if (typeof v === 'string' && v.trim())
|
|
35056
|
+
return v.trim();
|
|
35057
|
+
}
|
|
35058
|
+
return type;
|
|
35059
|
+
}
|
|
35060
|
+
/**
|
|
35061
|
+
* Résout la destination d'un clic de palette.
|
|
35062
|
+
*
|
|
35063
|
+
* `selectionId` est le composant actuellement sélectionné — un conteneur accueille, un
|
|
35064
|
+
* composant simple fait poser à côté de lui, chez son parent.
|
|
35065
|
+
*/
|
|
35066
|
+
function atelierCibleDePose(layout, selectionId, cle) {
|
|
35067
|
+
const auPlan = {
|
|
35068
|
+
dansId: null,
|
|
35069
|
+
pieceACreer: null,
|
|
35070
|
+
chemin: [],
|
|
35071
|
+
possible: atelierAccepte(null, cle),
|
|
35072
|
+
};
|
|
35073
|
+
if (!selectionId)
|
|
35074
|
+
return auPlan;
|
|
35075
|
+
const sel = atelierTrouver(layout, selectionId);
|
|
35076
|
+
if (!sel)
|
|
35077
|
+
return auPlan;
|
|
35078
|
+
// Un CONTENEUR sélectionné accueille ; un composant simple fait poser chez son parent,
|
|
35079
|
+
// donc à côté de lui — le geste que l'on attend quand on vient d'en poser un.
|
|
35080
|
+
const estConteneur = !!atelierComposant(sel.item.type)?.conteneur;
|
|
35081
|
+
const hote = estConteneur ? sel.item : sel.parentId ? atelierTrouver(layout, sel.parentId)?.item : null;
|
|
35082
|
+
if (!hote)
|
|
35083
|
+
return auPlan;
|
|
35084
|
+
if (atelierAccepte(hote.type, cle)) {
|
|
35085
|
+
return { dansId: hote.id, pieceACreer: null, chemin: [hote.type], possible: true };
|
|
35086
|
+
}
|
|
35087
|
+
// L'hôte refuse. Peut-on DESCENDRE dans sa pièce ? Seulement s'il n'a qu'un type de
|
|
35088
|
+
// pièce et que cette pièce accueille elle-même quelque chose.
|
|
35089
|
+
const pieces = atelierPiecesDe(hote.type);
|
|
35090
|
+
const piece = pieces.length === 1 ? pieces[0] : null;
|
|
35091
|
+
if (!piece || !atelierComposant(piece)?.conteneur || !atelierAccepte(piece, cle)) {
|
|
35092
|
+
return { dansId: hote.id, pieceACreer: null, chemin: [hote.type], possible: false };
|
|
35093
|
+
}
|
|
35094
|
+
const posees = (hote.children ?? []).filter((e) => e.type === piece);
|
|
35095
|
+
if (!posees.length) {
|
|
35096
|
+
// Aucune pièce : on en crée une au passage. Elle sera VISIBLE (un onglet apparaît),
|
|
35097
|
+
// ce qui la distingue d'une structure fabriquée en douce.
|
|
35098
|
+
return { dansId: hote.id, pieceACreer: piece, chemin: [hote.type, piece], possible: true };
|
|
35099
|
+
}
|
|
35100
|
+
// La pièce COURANTE, c'est-à-dire celle qu'on voit : en mode design le canevas est
|
|
35101
|
+
// inerte (les onglets ne se cliquent pas), donc l'affichage suit `activeIndex`, que
|
|
35102
|
+
// l'inspecteur expose. Sans prop exploitable, la première — comme à l'écran.
|
|
35103
|
+
const brut = Number(hote.props?.['activeIndex']);
|
|
35104
|
+
const i = Number.isInteger(brut) && brut >= 0 && brut < posees.length ? brut : 0;
|
|
35105
|
+
const courante = posees[i];
|
|
35106
|
+
return {
|
|
35107
|
+
dansId: courante.id,
|
|
35108
|
+
pieceACreer: null,
|
|
35109
|
+
chemin: [hote.type, libelle(courante.props, courante.type)],
|
|
35110
|
+
possible: true,
|
|
35111
|
+
};
|
|
35112
|
+
}
|
|
35113
|
+
/**
|
|
35114
|
+
* Les valeurs de DÉPART d'un composant qu'on pose : le texte projeté (`contenu=`) et
|
|
35115
|
+
* les entrées (`pose-*`) du catalogue.
|
|
35116
|
+
*
|
|
35117
|
+
* Extrait ici parce que DEUX poseurs doivent l'appliquer, et à DEUX endroits chacun :
|
|
35118
|
+
* au composant cliqué, et à la pièce d'hôte que le routage crée au passage. Cette
|
|
35119
|
+
* seconde application manquait — un onglet né du routage arrivait sans libellé, donc
|
|
35120
|
+
* invisible dans la barre (mesuré au clic dans le builder le 27/08). Un composant posé
|
|
35121
|
+
* sans ses valeurs de départ est une coquille, c'était déjà la leçon du 24/08.
|
|
35122
|
+
*/
|
|
35123
|
+
function atelierProposDePose(cle) {
|
|
35124
|
+
const c = atelierComposant(cle);
|
|
35125
|
+
if (!c)
|
|
35126
|
+
return {};
|
|
35127
|
+
return {
|
|
35128
|
+
...c.proposDeDepart,
|
|
35129
|
+
...(c.contenu ? { __contenu: c.contenu } : {}),
|
|
35130
|
+
};
|
|
35131
|
+
}
|
|
35132
|
+
|
|
34603
35133
|
/**
|
|
34604
35134
|
* Le code Angular d'une maquette — la sortie qui distingue cet atelier d'un Figma.
|
|
34605
35135
|
*
|
|
@@ -34668,9 +35198,15 @@ function ouvrante(item) {
|
|
|
34668
35198
|
}
|
|
34669
35199
|
return { balise: c.balise, attribut: c.attribut ? ` ${c.attribut}` : '' };
|
|
34670
35200
|
}
|
|
34671
|
-
/**
|
|
35201
|
+
/**
|
|
35202
|
+
* Tous les items, à TOUTES les profondeurs — les balayages (imports, manques) doivent
|
|
35203
|
+
* descendre jusqu'au bout. Une descente d'un seul cran oubliait les composants posés
|
|
35204
|
+
* dans un onglet : le code généré les écrivait sans les importer, donc il ne compilait
|
|
35205
|
+
* pas chez qui le collait.
|
|
35206
|
+
*/
|
|
34672
35207
|
function tousLesItems(layout) {
|
|
34673
|
-
|
|
35208
|
+
const descendre = (items) => items.flatMap((it) => [it, ...descendre(it.children ?? [])]);
|
|
35209
|
+
return descendre(layout.items);
|
|
34674
35210
|
}
|
|
34675
35211
|
/** Les entrées requises qu'aucune valeur ne remplit — nommées, jamais inventées. */
|
|
34676
35212
|
function atelierManques(layout) {
|
|
@@ -34817,5 +35353,5 @@ function atelierCode(layout, titre = 'Maquette') {
|
|
|
34817
35353
|
* Generated bundle index. Do not edit.
|
|
34818
35354
|
*/
|
|
34819
35355
|
|
|
34820
|
-
export { ATELIER_BORNES, ATELIER_COLONNES, ATELIER_STYLES_PLAN, BanGeocoder, CAD_BREAKPOINTS, CAD_CHART_PALETTE, CAD_COLOR_PRESETS, CAD_DEFAULT_BASEMAPS, CAD_DEFAULT_PRIORITY_BREAKPOINTS, CAD_DIALOG_DATA, CAD_FILTER_OPERATORS, CAD_GEOCODER, CAD_ICONS, CAD_ICONS_CEREMA, CAD_ICONS_CORE, CAD_ICONS_DATA, CAD_ICONS_FILES, CAD_ICONS_GEO, CAD_ICONS_SUBSET, CAD_ICONS_TOKEN, CAD_ICONS_UI, CAD_ICON_ALIASES, CAD_ICON_CATEGORIES, CAD_MAPLIBRE_CSS_URL, CAD_MAP_CHILD, CAD_MAP_DEFAULTS, CAD_MAP_GLOBAL_STYLES, CAD_MAP_GLYPHS, CAD_MAP_PALETTE, CAD_MASK_PRESETS, CAD_MOBILE_BREAKPOINT, CAD_RECURRENCE_INTERNE, CAD_SELECT_POSITIONS, CAD_SELECT_TRIGGER_STYLES, CAD_SHEET_DATA, CAD_SHELL, CAD_TOUCH_DENSITY, CadAccordionComponent, CadAccordionPanelComponent, CadAppShellComponent, CadAvatarComponent, CadAvatarGroupComponent, CadBadgeComponent, CadBadgeDirective, CadBlockDirective, CadBlockOverlayComponent, CadBlockUiComponent, CadBottomNavComponent, CadBreadcrumbComponent, CadBreadcrumbItemDirective, CadBreakpointService, CadButtonComponent, CadButtonGroupComponent, CadCalendarComponent, CadCaptionDirective, CadCardComponent, CadCardDirective, CadCardHeaderDirective, CadCarouselComponent, CadCarouselItemDirective, CadCascadeSelectComponent, CadCellTemplateDirective, CadCenterComponent, CadChartComponent, CadCheckboxComponent, CadChipComponent, CadClusterComponent, CadColDirective, CadColorpickerComponent, CadColumnComponent, CadComboComponent, CadConfirmContentComponent, CadConfirmDialogComponent, CadConfirmService, CadContainerComponent, CadDataviewComponent, CadDataviewGridDirective, CadDataviewListDirective, CadDatepickerComponent, CadDialogComponent, CadDialogContainerComponent, CadDialogFooterDirective, CadDialogHeaderDirective, CadDialogRef, CadDialogService, CadDividerComponent, CadDrawerComponent, CadEditFocusDirective, CadEditorTemplateDirective, CadEmptyDirective, CadFieldComponent, CadFieldsetComponent, CadFieldsetLegendDirective, CadFilterChipComponent, CadFilterTemplateDirective, CadGanttComponent, CadGeocodingService, CadGridComponent, CadGroupFooterDirective, CadGroupHeaderDirective, CadHeaderTemplateDirective, CadIconComponent, CadIconRegistry, CadIfDirective, CadImageComponent, CadInplaceComponent, CadInplaceContentDirective, CadInplaceDisplayDirective, CadInputDirective, CadJsonEditorComponent, CadKeyFilterDirective, CadListEmptyDirective, CadListFooterDirective, CadListHeaderDirective, CadListItemDirective, CadListboxComponent, CadMapBasemapRegistry, CadMapBasemapsComponent, CadMapCardComponent, CadMapChromeComponent, CadMapComponent, CadMapDrawEngine, CadMapLayerComponent, CadMapLayerGroupComponent, CadMapLayerToggleComponent, CadMapLegendComponent, CadMapMenuComponent, CadMapPanelComponent, CadMapPanels, CadMapRailComponent, CadMapRailItemComponent, CadMapSearchComponent, CadMapSectionComponent, CadMaskDirective, CadMenuComponent, CadMenubarComponent, CadMessageComponent, CadMeterComponent, CadMeterLabelDirective, CadMultiselectComponent, CadNavDrawerComponent, CadNavDrawerFooterDirective, CadNavDrawerHeaderDirective, CadNumberComponent, CadOptionListComponent, CadOrderlistComponent, CadOrgNodeDirective, CadOrgchartComponent, CadOverlayBase, CadPaginatorComponent, CadPanelComponent, CadPanelContentDirective, CadPanelHeaderDirective, CadPanelHeadingDirective, CadPasswordComponent, CadPicklistComponent, CadPopoverComponent, CadProgressComponent, CadRadioComponent, CadRadioGroupComponent, CadRatingComponent, CadRowActionsDirective, CadRowCountDirective, CadRowExpansionDirective, CadSchedulerComponent, CadScrollTopComponent, CadSegmentedComponent, CadSelectBase, CadSelectComponent, CadSelectEmptyDirective, CadSelectFooterDirective, CadSelectHeaderDirective, CadSelectItemDirective, CadSelectSelectedDirective, CadSheetContainerComponent, CadSheetRef, CadSheetService, CadSidebarComponent, CadSidebarPanelDirective, CadSkeletonComponent, CadSliderComponent, CadSpacerComponent, CadSpeedDialComponent, CadSpinnerComponent, CadSplitButtonComponent, CadSplitComponent, CadSplitterComponent, CadSplitterPanelComponent, CadStackComponent, CadStepComponent, CadStepperComponent, CadSwitchComponent, CadTabComponent, CadTabContentDirective, CadTabLabelDirective, CadTableBase, CadTableComponent, CadTableEdit, CadTableEditUi, CadTableFooterDirective, CadTablePanelComponent, CadTableResponsive, CadTableSelection, CadTableSticky, CadTableVirtual, CadTabsComponent, CadTagComponent, CadTaskCardDirective, CadTaskRowDirective, CadTaskboardComponent, CadTimeAxis, CadTimelineComponent, CadTimelineContentDirective, CadTimelineMarkerDirective, CadTimelineOppositeDirective, CadToastComponent, CadToastItemDirective, CadToastService, CadToggleButtonComponent, CadTooltipComponent, CadTooltipDirective, CadTreeAdapter, CadTreeComponent, CadTreeNodeDirective, CadTreeselectComponent, CadUploadComponent, CadUploadContentDirective, CadUploadEmptyDirective, CadUploadItemDirective, CadValueAccessor, CadWorkCalendar, MAPLIBRE_MIN_CSS, REGISTRE, addDays, addMonths, addYears, atelierAjouter, atelierBalise, atelierChercher, atelierCleDeSymbole, atelierCode, atelierComposant, atelierCompter, atelierControle, atelierDefinirProp, atelierDeplacer, atelierGabarit, atelierGroupes, atelierImports, atelierLayoutVide, atelierManques, atelierNomDeClasse, atelierNormaliser, atelierNouvelId, atelierPalette, atelierPoser, atelierPremierePlaceLibre, atelierRecompacter, atelierRedimensionner, atelierReinitialiserIds, atelierReordonnerEnfant, atelierRetirer, atelierSelecteurDeClasse, atelierTrouver, cadAggregate, cadApplyColumnOrder, cadApplyMask, cadArea, cadAutosizeWidth, cadBasemapThumbnail, cadBoundsOf, cadCategories, cadCentroid, cadClipFenetre, cadColorExpr, cadCompare, cadCompareRank, cadCurrentOperator, cadDebutSemaine, cadDefaultMatchMode, cadDistance, cadDownloadCsv, cadDurationToMinutes, cadEstBandeau, cadExpandOccurrences, cadFilterData, cadFilterKindOf, cadFilterOperators, cadFilterRows, cadFindLinkCycle, cadFmtArea, cadFmtLength, cadFormatCell, cadFormatColor, cadFormatDuration, cadFormatSize, cadFrenchHolidays, cadGanttRows, cadGap, cadGeoJSONStats, cadGeometryKinds, cadHeaderMenuItems, cadHighlightJson, cadHslToRgb, cadHsvToRgb, cadId, cadIsGroupKey, cadIsRank, cadJsonErrorPos, cadLegendFromStyle, cadLength, cadMapEstVivante, cadMapLayerOf, cadMapLayersOf, cadMatch, cadMinuit, cadMonthGrid, cadMoveColumn, cadMoveItems, cadNormalize, cadNormalizeOptions, cadNormalizePlan, cadNumberExpr, cadNumeroJour, cadPackDay, cadPackLanes, cadPadBounds, cadParseColor, cadParseDuration, cadParseRRule, cadParseResponsive, cadPlanHeader, cadPlanTicks, cadPointeFleche, cadProjeterClavier, cadProjeterCreation, cadProjeterEdition, cadProjeterMois, cadPropsTable, cadRankBetween, cadRankFirst, cadRankLast, cadRankSequence, cadResolve, cadResolveResponsive, cadResponsive, cadRgbToHsl, cadRgbToHsv, cadRingArea, cadRouterLien, cadRowKey, cadRowPredicate, cadSameValue, cadScaleNext, cadScaleStart, cadSchedulerPartition, cadSortData, cadStartResize, cadStyleToExpressions, cadUnmask, cadUnscheduled, cadValidateGeoJSON, cadValueForOperator, cadWeekBands, cadWriteField, classeDe, compareDay, daysInMonth, endOfMonth, ensureMaplibreCss, formatDate, isBetweenDay, isSameDay, isSameMonth, isValidDate, isoOf, isoWeek, loadChartJs, loadMaplibre, monthNames, pad2, parseIso, parseWithFormat, provideCadIcons, startOfDay, startOfMonth, toDate, weekdayNames };
|
|
35356
|
+
export { ATELIER_BORNES, ATELIER_COLONNES, ATELIER_STYLES_PLAN, BanGeocoder, CAD_BREAKPOINTS, CAD_CHART_PALETTE, CAD_COLOR_PRESETS, CAD_DEFAULT_BASEMAPS, CAD_DEFAULT_PRIORITY_BREAKPOINTS, CAD_DIALOG_DATA, CAD_FILTER_OPERATORS, CAD_GEOCODER, CAD_ICONS, CAD_ICONS_CEREMA, CAD_ICONS_CORE, CAD_ICONS_DATA, CAD_ICONS_FILES, CAD_ICONS_GEO, CAD_ICONS_SUBSET, CAD_ICONS_TOKEN, CAD_ICONS_UI, CAD_ICON_ALIASES, CAD_ICON_CATEGORIES, CAD_MAPLIBRE_CSS_URL, CAD_MAP_CHILD, CAD_MAP_DEFAULTS, CAD_MAP_GLOBAL_STYLES, CAD_MAP_GLYPHS, CAD_MAP_PALETTE, CAD_MASK_PRESETS, CAD_MOBILE_BREAKPOINT, CAD_RECURRENCE_INTERNE, CAD_SELECT_POSITIONS, CAD_SELECT_TRIGGER_STYLES, CAD_SHEET_DATA, CAD_SHELL, CAD_TOUCH_DENSITY, CadAccordionComponent, CadAccordionPanelComponent, CadAppShellComponent, CadAvatarComponent, CadAvatarGroupComponent, CadBadgeComponent, CadBadgeDirective, CadBlockDirective, CadBlockOverlayComponent, CadBlockUiComponent, CadBottomNavComponent, CadBreadcrumbComponent, CadBreadcrumbItemDirective, CadBreakpointService, CadButtonComponent, CadButtonGroupComponent, CadCalendarComponent, CadCaptionDirective, CadCardComponent, CadCardDirective, CadCardHeaderDirective, CadCarouselComponent, CadCarouselItemDirective, CadCascadeSelectComponent, CadCellTemplateDirective, CadCenterComponent, CadChartComponent, CadCheckboxComponent, CadChipComponent, CadClusterComponent, CadColDirective, CadColorpickerComponent, CadColumnComponent, CadComboComponent, CadConfirmContentComponent, CadConfirmDialogComponent, CadConfirmService, CadContainerComponent, CadDataviewComponent, CadDataviewGridDirective, CadDataviewListDirective, CadDatepickerComponent, CadDialogComponent, CadDialogContainerComponent, CadDialogFooterDirective, CadDialogHeaderDirective, CadDialogRef, CadDialogService, CadDividerComponent, CadDrawerComponent, CadEditFocusDirective, CadEditorTemplateDirective, CadEmptyDirective, CadFieldComponent, CadFieldsetComponent, CadFieldsetLegendDirective, CadFilterChipComponent, CadFilterTemplateDirective, CadGanttComponent, CadGeocodingService, CadGridComponent, CadGroupFooterDirective, CadGroupHeaderDirective, CadHeaderTemplateDirective, CadIconComponent, CadIconRegistry, CadIfDirective, CadImageComponent, CadInplaceComponent, CadInplaceContentDirective, CadInplaceDisplayDirective, CadInputDirective, CadJsonEditorComponent, CadKeyFilterDirective, CadListEmptyDirective, CadListFooterDirective, CadListHeaderDirective, CadListItemDirective, CadListboxComponent, CadMapBasemapRegistry, CadMapBasemapsComponent, CadMapCardComponent, CadMapChromeComponent, CadMapComponent, CadMapDrawEngine, CadMapLayerComponent, CadMapLayerGroupComponent, CadMapLayerToggleComponent, CadMapLegendComponent, CadMapMenuComponent, CadMapPanelComponent, CadMapPanels, CadMapRailComponent, CadMapRailItemComponent, CadMapSearchComponent, CadMapSectionComponent, CadMaskDirective, CadMenuComponent, CadMenubarComponent, CadMessageComponent, CadMeterComponent, CadMeterLabelDirective, CadMultiselectComponent, CadNavDrawerComponent, CadNavDrawerFooterDirective, CadNavDrawerHeaderDirective, CadNumberComponent, CadOptionListComponent, CadOrderlistComponent, CadOrgNodeDirective, CadOrgchartComponent, CadOverlayBase, CadPaginatorComponent, CadPanelComponent, CadPanelContentDirective, CadPanelHeaderDirective, CadPanelHeadingDirective, CadPasswordComponent, CadPicklistComponent, CadPopoverComponent, CadProgressComponent, CadRadioComponent, CadRadioGroupComponent, CadRatingComponent, CadRowActionsDirective, CadRowCountDirective, CadRowExpansionDirective, CadSchedulerComponent, CadScrollTopComponent, CadSegmentedComponent, CadSelectBase, CadSelectComponent, CadSelectEmptyDirective, CadSelectFooterDirective, CadSelectHeaderDirective, CadSelectItemDirective, CadSelectSelectedDirective, CadSheetContainerComponent, CadSheetRef, CadSheetService, CadSidebarComponent, CadSidebarPanelDirective, CadSkeletonComponent, CadSliderComponent, CadSpacerComponent, CadSpeedDialComponent, CadSpinnerComponent, CadSplitButtonComponent, CadSplitComponent, CadSplitterComponent, CadSplitterPanelComponent, CadStackComponent, CadStepComponent, CadStepperComponent, CadSwitchComponent, CadTabComponent, CadTabContentDirective, CadTabLabelDirective, CadTableBase, CadTableComponent, CadTableEdit, CadTableEditUi, CadTableFooterDirective, CadTablePanelComponent, CadTableResponsive, CadTableSelection, CadTableSticky, CadTableVirtual, CadTabsComponent, CadTagComponent, CadTaskCardDirective, CadTaskRowDirective, CadTaskboardComponent, CadTimeAxis, CadTimelineComponent, CadTimelineContentDirective, CadTimelineMarkerDirective, CadTimelineOppositeDirective, CadToastComponent, CadToastItemDirective, CadToastService, CadToggleButtonComponent, CadTooltipComponent, CadTooltipDirective, CadTreeAdapter, CadTreeComponent, CadTreeNodeDirective, CadTreeselectComponent, CadUploadComponent, CadUploadContentDirective, CadUploadEmptyDirective, CadUploadItemDirective, CadValueAccessor, CadWorkCalendar, MAPLIBRE_MIN_CSS, REGISTRE, addDays, addMonths, addYears, atelierAccepte, atelierAdopterIds, atelierAjouter, atelierBalise, atelierChercher, atelierCibleDePose, atelierCleDeSymbole, atelierCode, atelierComposant, atelierCompter, atelierControle, atelierDefinirProp, atelierDeplacer, atelierGabarit, atelierGroupes, atelierImports, atelierLayoutVide, atelierManques, atelierNomDeClasse, atelierNormaliser, atelierNouvelId, atelierPalette, atelierPiecesDe, atelierPoser, atelierPremierePlaceLibre, atelierProposDePose, atelierRecompacter, atelierRedimensionner, atelierReinitialiserIds, atelierReordonnerEnfant, atelierRetirer, atelierSelecteurDeClasse, atelierTrouver, cadAggregate, cadApplyColumnOrder, cadApplyMask, cadArea, cadAutosizeWidth, cadBasemapThumbnail, cadBoundsOf, cadCategories, cadCentroid, cadClipFenetre, cadColorExpr, cadCompare, cadCompareRank, cadCurrentOperator, cadDebutSemaine, cadDefaultMatchMode, cadDistance, cadDownloadCsv, cadDurationToMinutes, cadEstBandeau, cadExpandOccurrences, cadFilterData, cadFilterKindOf, cadFilterOperators, cadFilterRows, cadFindLinkCycle, cadFmtArea, cadFmtLength, cadFormatCell, cadFormatColor, cadFormatDuration, cadFormatSize, cadFrenchHolidays, cadGanttRows, cadGap, cadGeoJSONStats, cadGeometryKinds, cadHeaderMenuItems, cadHighlightJson, cadHslToRgb, cadHsvToRgb, cadId, cadIsGroupKey, cadIsRank, cadJsonErrorPos, cadLegendFromStyle, cadLength, cadMapEstVivante, cadMapLayerOf, cadMapLayersOf, cadMatch, cadMinuit, cadMonthGrid, cadMoveColumn, cadMoveItems, cadNormalize, cadNormalizeOptions, cadNormalizePlan, cadNumberExpr, cadNumeroJour, cadPackDay, cadPackLanes, cadPadBounds, cadParseColor, cadParseDuration, cadParseRRule, cadParseResponsive, cadPlanHeader, cadPlanTicks, cadPointeFleche, cadProjeterClavier, cadProjeterCreation, cadProjeterEdition, cadProjeterMois, cadPropsTable, cadRankBetween, cadRankFirst, cadRankLast, cadRankSequence, cadResolve, cadResolveResponsive, cadResponsive, cadRgbToHsl, cadRgbToHsv, cadRingArea, cadRouterLien, cadRowKey, cadRowPredicate, cadSameValue, cadScaleNext, cadScaleStart, cadSchedulerPartition, cadSortData, cadStartResize, cadStyleToExpressions, cadUnmask, cadUnscheduled, cadValidateGeoJSON, cadValueForOperator, cadWeekBands, cadWriteField, classeDe, compareDay, daysInMonth, endOfMonth, ensureMaplibreCss, estHoteAPieces, formatDate, isBetweenDay, isSameDay, isSameMonth, isValidDate, isoOf, isoWeek, loadChartJs, loadMaplibre, monthNames, pad2, parseIso, parseWithFormat, provideCadIcons, startOfDay, startOfMonth, toDate, weekdayNames };
|
|
34821
35357
|
//# sourceMappingURL=cadriciel-ui.mjs.map
|