@prolibu-suite/cobalt-core 0.11.1 → 0.11.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/custom-elements.json +153 -34
- package/dist/cjs/co-button.cjs.entry.js +1 -1
- package/dist/cjs/co-chip_2.cjs.entry.js +2 -2
- package/dist/cjs/co-document-editor.cjs.entry.js +1 -1
- package/dist/cjs/co-modal.cjs.entry.js +27 -1
- package/dist/cjs/co-overlay.cjs.entry.js +205 -34
- package/dist/cjs/co-rich-text-editor.cjs.entry.js +2 -2
- package/dist/cjs/co-rich-text-viewer.cjs.entry.js +1 -1
- package/dist/cjs/co-toggle-button.cjs.entry.js +1 -1
- package/dist/cjs/cobalt.cjs.js +1 -1
- package/dist/cjs/{index-oMHzCXm6.js → index-BbSD1Eyw.js} +1 -1
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/{pagination-DV43TRj9.js → pagination-S2sSAgdl.js} +26 -2
- package/dist/cobalt/cobalt.esm.js +1 -1
- package/dist/cobalt/{p-d6e7c258.entry.js → p-02ff847e.entry.js} +1 -1
- package/dist/cobalt/{p-87e62e2b.entry.js → p-12914c0a.entry.js} +1 -1
- package/dist/cobalt/p-38eb2615.entry.js +1 -0
- package/dist/cobalt/{p-47eca182.entry.js → p-6c7e423c.entry.js} +1 -1
- package/dist/cobalt/p-93063876.entry.js +1 -0
- package/dist/cobalt/p-9b114836.entry.js +1 -0
- package/dist/cobalt/{p-RVQJEYxa.js → p-Ch-Tygdb.js} +1 -1
- package/dist/cobalt/p-DGLDAl09.js +1 -0
- package/dist/cobalt/{p-3b6efb79.entry.js → p-bb7bbe70.entry.js} +1 -1
- package/dist/cobalt/p-e5f0d560.entry.js +1 -0
- package/dist/collection/components/co-autocomplete/co-autocomplete.js +1 -1
- package/dist/collection/components/co-avatar-group/co-avatar-group.js +1 -1
- package/dist/collection/components/co-button/co-button.css +15 -0
- package/dist/collection/components/co-checkbox-group/co-checkbox-group.js +1 -1
- package/dist/collection/components/co-chip/co-chip.css +16 -11
- package/dist/collection/components/co-color-area/co-color-area.js +2 -2
- package/dist/collection/components/co-color-slider/co-color-slider.js +1 -1
- package/dist/collection/components/co-combobox/co-combobox.js +1 -1
- package/dist/collection/components/co-command-search/co-command-search.js +1 -1
- package/dist/collection/components/co-data-table/co-data-table.js +1 -1
- package/dist/collection/components/co-date-range-picker/co-date-range-picker.js +2 -2
- package/dist/collection/components/co-document-editor/co-document-editor.js +5 -5
- package/dist/collection/components/co-modal/co-modal.js +68 -1
- package/dist/collection/components/co-option-list/co-option-list.css +30 -4
- package/dist/collection/components/co-overlay/co-overlay.css +7 -0
- package/dist/collection/components/co-overlay/co-overlay.js +130 -26
- package/dist/collection/components/co-overlay/focusTrap.js +111 -3
- package/dist/collection/components/co-popover/co-popover.js +1 -1
- package/dist/collection/components/co-radio-group/co-radio-group.js +1 -1
- package/dist/collection/components/co-ref-field/co-ref-field.js +4 -4
- package/dist/collection/components/co-segmented-bar/co-segmented-bar.js +1 -1
- package/dist/collection/components/co-select/co-select.js +1 -1
- package/dist/collection/components/co-sidebar-nav/co-sidebar-nav.js +1 -1
- package/dist/collection/components/co-toast/co-toast.js +2 -2
- package/dist/collection/components/co-toggle-button/co-toggle-button.css +43 -13
- package/dist/collection/components/co-transfer-list/co-transfer-list.js +1 -1
- package/dist/collection/components/co-tree-item/co-tree-item.js +2 -2
- package/dist/components/co-autocomplete.js +1 -1
- package/dist/components/co-button.js +1 -1
- package/dist/components/co-chip.js +1 -1
- package/dist/components/co-column-picker.js +1 -1
- package/dist/components/co-combobox.js +1 -1
- package/dist/components/co-command-search.js +1 -1
- package/dist/components/co-data-table.js +1 -1
- package/dist/components/co-date-picker.js +1 -1
- package/dist/components/co-date-range-picker.js +1 -1
- package/dist/components/co-date-range.js +1 -1
- package/dist/components/co-date-time-picker.js +1 -1
- package/dist/components/co-document-editor.js +1 -1
- package/dist/components/co-drawer.js +1 -1
- package/dist/components/co-modal.js +1 -1
- package/dist/components/co-option-list.js +1 -1
- package/dist/components/co-overlay.js +1 -1
- package/dist/components/co-ref-field.js +1 -1
- package/dist/components/co-rich-text-editor.js +1 -1
- package/dist/components/co-rich-text-viewer.js +1 -1
- package/dist/components/co-toggle-button.js +1 -1
- package/dist/components/{p-BVdCvEza.js → p-BI_VaFsx.js} +1 -1
- package/dist/components/{p-Cnfd6Zze.js → p-BqFBZ1PT.js} +1 -1
- package/dist/components/{p-Du8EpQb-.js → p-C_6szR7t.js} +1 -1
- package/dist/components/{p-RVQJEYxa.js → p-Ch-Tygdb.js} +1 -1
- package/dist/components/{p-zJ3pjFzW.js → p-DB8DGMc-.js} +1 -1
- package/dist/components/p-DGLDAl09.js +1 -0
- package/dist/components/{p-Hi57w2_2.js → p-DhPxNA2f.js} +1 -1
- package/dist/components/p-wUXcJGdy.js +1 -0
- package/dist/esm/co-button.entry.js +1 -1
- package/dist/esm/co-chip_2.entry.js +2 -2
- package/dist/esm/co-document-editor.entry.js +1 -1
- package/dist/esm/co-modal.entry.js +28 -2
- package/dist/esm/co-overlay.entry.js +205 -34
- package/dist/esm/co-rich-text-editor.entry.js +2 -2
- package/dist/esm/co-rich-text-viewer.entry.js +1 -1
- package/dist/esm/co-toggle-button.entry.js +1 -1
- package/dist/esm/cobalt.js +1 -1
- package/dist/esm/{index-Cpo8HTwr.js → index-CgyOJePd.js} +1 -1
- package/dist/esm/loader.js +1 -1
- package/dist/esm/{pagination-D9OfZUnY.js → pagination-BzrIQtrk.js} +26 -2
- package/dist/types/components/co-modal/co-modal.d.ts +23 -0
- package/dist/types/components/co-overlay/co-overlay.d.ts +29 -1
- package/dist/types/components/co-overlay/focusTrap.d.ts +24 -3
- package/dist/types/components.d.ts +21 -2
- package/package.json +4 -4
- package/dist/cobalt/p-1a5bec8c.entry.js +0 -1
- package/dist/cobalt/p-67a024dd.entry.js +0 -1
- package/dist/cobalt/p-9ee5bef3.entry.js +0 -1
- package/dist/cobalt/p-B1JT7us1.js +0 -1
- package/dist/cobalt/p-c4c997f3.entry.js +0 -1
- package/dist/components/p-B1JT7us1.js +0 -1
- package/dist/components/p-nrwDl_gx.js +0 -1
|
@@ -55,20 +55,112 @@ function resolveTabIndex(count, activeIndex, shiftKey) {
|
|
|
55
55
|
// Forward: from the last element (or from outside) wrap to the first.
|
|
56
56
|
return activeIndex === -1 || activeIndex >= count - 1 ? 0 : activeIndex + 1;
|
|
57
57
|
}
|
|
58
|
+
// ── Recorrido compuesto (QA 2026-09-24, «Generar contrato» de contratos V2) ──
|
|
59
|
+
// El foco nunca entraba ni quedaba atrapado en un co-modal: `getFocusableElements`
|
|
60
|
+
// solo mira el light DOM de co-overlay (el frame del modal: el ✕). El contenido
|
|
61
|
+
// del consumidor llega por DOS <slot> (el de co-overlay y el del frame) y los
|
|
62
|
+
// controles reales viven en el shadow de cada co-* (el <button> de co-button, el
|
|
63
|
+
// <input> de co-input). El recorrido sigue el árbol PLANO: baja por shadowRoots
|
|
64
|
+
// y, en cada <slot>, por sus asignados — o por su contenido por defecto si no
|
|
65
|
+
// tiene. Todo esto corre solo en el navegador (abrir la trampa / cada Tab).
|
|
66
|
+
/** Hijos en el árbol plano: el shadow del host, los asignados de un slot o los hijos. */
|
|
67
|
+
function composedChildren(el) {
|
|
68
|
+
if (el.shadowRoot)
|
|
69
|
+
return Array.from(el.shadowRoot.children);
|
|
70
|
+
if (el.tagName === 'SLOT') {
|
|
71
|
+
const assigned = el.assignedElements({ flatten: true });
|
|
72
|
+
return assigned.length ? assigned : Array.from(el.children);
|
|
73
|
+
}
|
|
74
|
+
return Array.from(el.children);
|
|
75
|
+
}
|
|
76
|
+
/** Subárbol fuera de la trampa entero: oculto a AT o inerte. */
|
|
77
|
+
function isExcludedSubtree(el) {
|
|
78
|
+
return el.getAttribute('aria-hidden') === 'true' || el.hasAttribute('inert');
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Parada de Tab: matchea el selector, no está deshabilitado, no se sacó del
|
|
82
|
+
* orden con tabindex negativo (los botones internos de un trigger co-* —clear,
|
|
83
|
+
* chips— van con `tabIndex={-1}`, y `button:not([disabled])` los matchearía
|
|
84
|
+
* igual), tiene caja (offsetParent null = display:none; getClientRects cubre
|
|
85
|
+
* position:fixed) y no es `visibility:hidden`: un acordeón o fieldset colapsado
|
|
86
|
+
* conserva la caja pero el navegador no le da el foco, y la trampa lo elegiría
|
|
87
|
+
* igual → Tab clavado (WCAG 2.1.2). Sin la API (navegador viejo, jsdom) no filtra.
|
|
88
|
+
*/
|
|
89
|
+
function isTabStop(el) {
|
|
90
|
+
var _a, _b;
|
|
91
|
+
if (!((_a = el.matches) === null || _a === void 0 ? void 0 : _a.call(el, FOCUSABLE_SELECTOR)) || el.hasAttribute('disabled'))
|
|
92
|
+
return false;
|
|
93
|
+
const tabindex = el.getAttribute('tabindex');
|
|
94
|
+
if (tabindex !== null && Number(tabindex) < 0)
|
|
95
|
+
return false;
|
|
96
|
+
if (el.offsetParent === null && el.getClientRects().length === 0)
|
|
97
|
+
return false;
|
|
98
|
+
return ((_b = el.checkVisibility) === null || _b === void 0 ? void 0 : _b.call(el, { visibilityProperty: true })) !== false;
|
|
99
|
+
}
|
|
58
100
|
/**
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
* out of scope — the common dialog/modal content lives in the slotted subtree.)
|
|
101
|
+
* Recorre en orden del árbol plano los descendientes compuestos de `root` (sin
|
|
102
|
+
* incluirlo) hasta que `visit` devuelve true. Poda aria-hidden / inert.
|
|
62
103
|
*/
|
|
63
|
-
function
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
104
|
+
function walkComposed(root, visit) {
|
|
105
|
+
const step = (node) => {
|
|
106
|
+
if (isExcludedSubtree(node))
|
|
107
|
+
return false;
|
|
108
|
+
if (visit(node))
|
|
109
|
+
return true;
|
|
110
|
+
return composedChildren(node).some(step);
|
|
111
|
+
};
|
|
112
|
+
composedChildren(root).some(step);
|
|
113
|
+
}
|
|
114
|
+
/** Primer descendiente compuesto que cumple `match`, en orden del árbol plano. */
|
|
115
|
+
function findComposed(root, match) {
|
|
116
|
+
let found = null;
|
|
117
|
+
walkComposed(root, (el) => {
|
|
118
|
+
if (!match(el))
|
|
119
|
+
return false;
|
|
120
|
+
found = el;
|
|
121
|
+
return true;
|
|
122
|
+
});
|
|
123
|
+
return found;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Paradas de Tab dentro de `root` en el árbol COMPUESTO (shadowRoots + slots
|
|
127
|
+
* asignados), con las mismas exclusiones que `getFocusableElements`.
|
|
128
|
+
*/
|
|
129
|
+
function getComposedFocusables(root) {
|
|
130
|
+
const out = [];
|
|
131
|
+
walkComposed(root, (el) => {
|
|
132
|
+
if (isTabStop(el))
|
|
133
|
+
out.push(el);
|
|
134
|
+
return false;
|
|
135
|
+
});
|
|
136
|
+
return out;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Dónde cae el foco al abrir la trampa: el primer `[autofocus]` del recorrido
|
|
140
|
+
* compuesto —si es un host con shadow (`<co-input autofocus>`), su primer
|
|
141
|
+
* enfocable compuesto—; si no hay, la primera parada de Tab. `null` = nada
|
|
142
|
+
* enfocable (el llamador cae al contenedor).
|
|
143
|
+
*/
|
|
144
|
+
function resolveInitialFocus(root) {
|
|
145
|
+
const autofocus = findComposed(root, (el) => el.hasAttribute('autofocus'));
|
|
146
|
+
if (autofocus) {
|
|
147
|
+
if (isTabStop(autofocus))
|
|
148
|
+
return autofocus;
|
|
149
|
+
const inner = autofocus.shadowRoot ? getComposedFocusables(autofocus)[0] : undefined;
|
|
150
|
+
if (inner)
|
|
151
|
+
return inner;
|
|
152
|
+
}
|
|
153
|
+
return findComposed(root, isTabStop);
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Con dos trampas abiertas (un confirm sobre un modal, un modal anidado) las dos
|
|
157
|
+
* escuchan el keydown de document: solo la capa MÁS RECIENTE maneja Tab.
|
|
158
|
+
*/
|
|
159
|
+
function isTopTrap(stack, id) {
|
|
160
|
+
return stack.length > 0 && stack[stack.length - 1] === id;
|
|
69
161
|
}
|
|
70
162
|
|
|
71
|
-
const coOverlayCss = () => `:host{display:contents}.co-overlay{position:fixed;inset:0;z-index:1000;margin:0;border:0;padding:0;width:auto;height:auto;max-width:none;max-height:none;overflow:visible;display:flex;align-items:center;justify-content:center;background:var(--co-overlay-bg, rgba(0, 0, 0, 0.4));-webkit-backdrop-filter:blur(var(--co-overlay-blur, 2px));backdrop-filter:blur(var(--co-overlay-blur, 2px));opacity:0;pointer-events:none;transition:opacity var(--co-motion-duration-fast) var(--co-motion-ease-in)}.co-overlay--open{opacity:1;pointer-events:auto;transition:opacity var(--co-motion-duration-base) var(--co-motion-ease-out)}`;
|
|
163
|
+
const coOverlayCss = () => `:host{display:contents}.co-overlay{position:fixed;inset:0;z-index:1000;margin:0;border:0;padding:0;width:auto;height:auto;max-width:none;max-height:none;overflow:visible;display:flex;align-items:center;justify-content:center;background:var(--co-overlay-bg, rgba(0, 0, 0, 0.4));-webkit-backdrop-filter:blur(var(--co-overlay-blur, 2px));backdrop-filter:blur(var(--co-overlay-blur, 2px));opacity:0;pointer-events:none;transition:opacity var(--co-motion-duration-fast) var(--co-motion-ease-in)}.co-overlay--open{opacity:1;pointer-events:auto;transition:opacity var(--co-motion-duration-base) var(--co-motion-ease-out)}.co-overlay--refront{transition:none !important}`;
|
|
72
164
|
|
|
73
165
|
/**
|
|
74
166
|
* Module-level body-scroll lock shared by every overlay instance.
|
|
@@ -96,6 +188,16 @@ function unlockBodyScroll() {
|
|
|
96
188
|
document.body.style.overflow = savedOverflow;
|
|
97
189
|
}
|
|
98
190
|
}
|
|
191
|
+
/**
|
|
192
|
+
* Pila de trampas de foco ABIERTAS, compartida por todas las instancias (como el
|
|
193
|
+
* scroll lock). Todas escuchan el keydown de document: con un confirm encima de
|
|
194
|
+
* un modal, las dos movían el foco en el mismo Tab. Solo la capa más reciente
|
|
195
|
+
* (`isTopTrap`) maneja Tab y el foco inicial.
|
|
196
|
+
*/
|
|
197
|
+
const trapStack = [];
|
|
198
|
+
let trapSeq = 0;
|
|
199
|
+
/** Clase del div mientras dura el re-apilado de `bringToFront()` (ver co-overlay.css). */
|
|
200
|
+
const REFRONT_CLASS = 'co-overlay--refront';
|
|
99
201
|
function nextFrame(cb) {
|
|
100
202
|
if (typeof requestAnimationFrame === 'function')
|
|
101
203
|
requestAnimationFrame(cb);
|
|
@@ -115,6 +217,11 @@ const CoOverlay = class {
|
|
|
115
217
|
* previously-focused element, moves focus into the overlay, cycles Tab /
|
|
116
218
|
* Shift+Tab within the slotted content, and restores focus on close.
|
|
117
219
|
* Default false → existing consumers are unchanged.
|
|
220
|
+
*
|
|
221
|
+
* The walk is COMPOSED (shadow roots + assigned slots): it reaches the
|
|
222
|
+
* consumer's content projected through a host's slots and the inner control
|
|
223
|
+
* of every co-* (a co-button's `<button>`). With several traps open, only the
|
|
224
|
+
* most recent one handles Tab.
|
|
118
225
|
*/
|
|
119
226
|
this.trapFocus = false;
|
|
120
227
|
/**
|
|
@@ -124,6 +231,10 @@ const CoOverlay = class {
|
|
|
124
231
|
this.closeOnEscape = false;
|
|
125
232
|
/** Whether THIS instance currently holds a scroll lock (prevents double-count). */
|
|
126
233
|
this.hasLock = false;
|
|
234
|
+
/** Identidad de esta instancia en `trapStack`. */
|
|
235
|
+
this.trapId = `co-overlay-trap-${++trapSeq}`;
|
|
236
|
+
/** Whether THIS instance is currently in `trapStack` (prevents double push). */
|
|
237
|
+
this.trapping = false;
|
|
127
238
|
// Origen de la pulsación en curso (ver isBackdropDismiss): un drag que
|
|
128
239
|
// empieza dentro del contenido y suelta en el fondo NO es un cierre —el
|
|
129
240
|
// navegador despacha ese `click` al ancestro común, el propio scrim—, ni
|
|
@@ -165,27 +276,55 @@ const CoOverlay = class {
|
|
|
165
276
|
else
|
|
166
277
|
this.releaseLock();
|
|
167
278
|
this.syncPopover();
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
this.restoreFocus();
|
|
173
|
-
}
|
|
279
|
+
this.syncTrap();
|
|
280
|
+
}
|
|
281
|
+
onTrapFocusChange() {
|
|
282
|
+
this.syncTrap();
|
|
174
283
|
}
|
|
175
284
|
componentDidLoad() {
|
|
176
285
|
// Handle the case where the overlay mounts already open.
|
|
177
286
|
if (this.open)
|
|
178
287
|
this.acquireLock();
|
|
179
288
|
this.syncPopover();
|
|
180
|
-
|
|
181
|
-
this.captureAndFocus();
|
|
289
|
+
this.syncTrap();
|
|
182
290
|
}
|
|
183
291
|
disconnectedCallback() {
|
|
184
292
|
// Safety: never leave the body locked if removed while open.
|
|
185
293
|
this.releaseLock();
|
|
186
|
-
// Safety: return focus if
|
|
187
|
-
|
|
188
|
-
|
|
294
|
+
// Safety: leave the trap stack and return focus if removed while trapping.
|
|
295
|
+
this.releaseTrap();
|
|
296
|
+
}
|
|
297
|
+
/**
|
|
298
|
+
* Re-promueve el scrim al TOPE del top layer (QA 2026-09-24, «Generar
|
|
299
|
+
* contrato»): un drawer abierto DESPUÉS de un modal pintaba encima, porque en
|
|
300
|
+
* el top layer gana el último promovido y no hay z-index que lo corrija.
|
|
301
|
+
* `hidePopover()` + `showPopover()` lo vuelven a meter último.
|
|
302
|
+
*
|
|
303
|
+
* No es un cierre: no emite `coClose` / `coAfterClose` / `coAfterOpen`, no
|
|
304
|
+
* toca `open` ni el scroll lock, y no re-anima la entrada (la clase
|
|
305
|
+
* `co-overlay--refront` anula la transición durante el re-show y se retira en
|
|
306
|
+
* el frame siguiente). Tampoco mueve el foco: si el re-show dispara los
|
|
307
|
+
* «popover focusing steps» (un `[autofocus]` adentro), se devuelve a donde
|
|
308
|
+
* estaba. No-op cerrado, sin Popover API o fuera del top layer.
|
|
309
|
+
*/
|
|
310
|
+
async bringToFront() {
|
|
311
|
+
const el = this.overlayEl;
|
|
312
|
+
if (!this.open || !el || typeof el.showPopover !== 'function')
|
|
313
|
+
return;
|
|
314
|
+
if (!el.matches(':popover-open'))
|
|
315
|
+
return;
|
|
316
|
+
const active = this.deepActiveElement();
|
|
317
|
+
el.classList.add(REFRONT_CLASS);
|
|
318
|
+
try {
|
|
319
|
+
el.hidePopover();
|
|
320
|
+
el.showPopover();
|
|
321
|
+
}
|
|
322
|
+
catch (_a) {
|
|
323
|
+
/* desconectado entre medio: no hay nada que re-apilar */
|
|
324
|
+
}
|
|
325
|
+
if (active && active.isConnected && this.deepActiveElement() !== active)
|
|
326
|
+
active.focus({ preventScroll: true });
|
|
327
|
+
nextFrame(() => el.classList.remove(REFRONT_CLASS));
|
|
189
328
|
}
|
|
190
329
|
acquireLock() {
|
|
191
330
|
if (this.hasLock)
|
|
@@ -223,19 +362,43 @@ const CoOverlay = class {
|
|
|
223
362
|
/* not connected yet, or already in the desired state */
|
|
224
363
|
}
|
|
225
364
|
}
|
|
226
|
-
/**
|
|
365
|
+
/** La trampa está activa exactamente mientras el overlay está abierto con `trapFocus`. */
|
|
366
|
+
syncTrap() {
|
|
367
|
+
if (this.open && this.trapFocus)
|
|
368
|
+
this.engageTrap();
|
|
369
|
+
else
|
|
370
|
+
this.releaseTrap();
|
|
371
|
+
}
|
|
372
|
+
engageTrap() {
|
|
373
|
+
if (this.trapping)
|
|
374
|
+
return;
|
|
375
|
+
this.trapping = true;
|
|
376
|
+
trapStack.push(this.trapId);
|
|
377
|
+
this.captureAndFocus();
|
|
378
|
+
}
|
|
379
|
+
releaseTrap() {
|
|
380
|
+
if (!this.trapping)
|
|
381
|
+
return;
|
|
382
|
+
this.trapping = false;
|
|
383
|
+
const i = trapStack.indexOf(this.trapId);
|
|
384
|
+
if (i >= 0)
|
|
385
|
+
trapStack.splice(i, 1);
|
|
386
|
+
this.restoreFocus();
|
|
387
|
+
}
|
|
388
|
+
/** Record the current focus and move it into the overlay (only while trapping). */
|
|
227
389
|
captureAndFocus() {
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
390
|
+
// El activo PROFUNDO: `document.activeElement` se queda en el host de un
|
|
391
|
+
// co-* (co-button), cuyo focus() no llega al <button> interno.
|
|
392
|
+
this.returnFocusEl = this.deepActiveElement();
|
|
231
393
|
// Defer so slotted content / the open transition is ready to take focus.
|
|
232
394
|
nextFrame(() => {
|
|
233
395
|
var _a;
|
|
234
|
-
|
|
396
|
+
// Una trampa abierta en el mismo frame por ENCIMA (confirm) se queda el foco.
|
|
397
|
+
if (!this.open || !this.trapping || !isTopTrap(trapStack, this.trapId))
|
|
235
398
|
return;
|
|
236
|
-
const
|
|
237
|
-
if (
|
|
238
|
-
|
|
399
|
+
const target = resolveInitialFocus(this.el);
|
|
400
|
+
if (target)
|
|
401
|
+
target.focus();
|
|
239
402
|
else
|
|
240
403
|
(_a = this.overlayEl) === null || _a === void 0 ? void 0 : _a.focus();
|
|
241
404
|
});
|
|
@@ -244,8 +407,9 @@ const CoOverlay = class {
|
|
|
244
407
|
restoreFocus() {
|
|
245
408
|
const target = this.returnFocusEl;
|
|
246
409
|
this.returnFocusEl = null;
|
|
247
|
-
|
|
248
|
-
|
|
410
|
+
// Desmontado mientras el overlay estaba abierto (el paso de un wizard): no hay adónde volver.
|
|
411
|
+
if (target && target.isConnected && typeof target.focus === 'function')
|
|
412
|
+
target.focus({ preventScroll: true });
|
|
249
413
|
}
|
|
250
414
|
/** Deepest active element, descending through nested shadow roots. */
|
|
251
415
|
deepActiveElement() {
|
|
@@ -264,12 +428,16 @@ const CoOverlay = class {
|
|
|
264
428
|
this.coClose.emit();
|
|
265
429
|
return;
|
|
266
430
|
}
|
|
267
|
-
if (this.
|
|
431
|
+
if (this.trapping && e.key === 'Tab' && isTopTrap(trapStack, this.trapId))
|
|
268
432
|
this.trapTab(e);
|
|
269
433
|
}
|
|
270
434
|
trapTab(e) {
|
|
271
435
|
var _a;
|
|
272
|
-
|
|
436
|
+
// Tab ya manejado por un control de adentro (co-tags-field agrega el tag, las listas de co-rich-text y
|
|
437
|
+
// CodeMirror indentan): el listener de document corre DESPUÉS y no le roba el foco.
|
|
438
|
+
if (e.defaultPrevented)
|
|
439
|
+
return;
|
|
440
|
+
const focusables = getComposedFocusables(this.el);
|
|
273
441
|
if (focusables.length === 0) {
|
|
274
442
|
// Nothing to move to — keep focus pinned to the overlay container.
|
|
275
443
|
e.preventDefault();
|
|
@@ -284,12 +452,15 @@ const CoOverlay = class {
|
|
|
284
452
|
focusables[nextIndex].focus();
|
|
285
453
|
}
|
|
286
454
|
render() {
|
|
287
|
-
return (h("div", { key: '
|
|
455
|
+
return (h("div", { key: 'e18d7b0e3ebd4933a78a9f2d39af6058ce429105', class: { 'co-overlay': true, 'co-overlay--open': this.open }, part: "overlay", popover: "manual", tabindex: this.trapFocus ? -1 : undefined, ref: (el) => (this.overlayEl = el), onPointerDown: this.handlePointerDown, onPointerUp: this.handlePointerUp, onClick: this.handleClick, onTransitionEnd: this.handleTransitionEnd }, h("slot", { key: '2f29233d44de8a0cc3100cfa08233cdc10ebf352' })));
|
|
288
456
|
}
|
|
289
457
|
get el() { return getElement(this); }
|
|
290
458
|
static get watchers() { return {
|
|
291
459
|
"open": [{
|
|
292
460
|
"onOpenChange": 0
|
|
461
|
+
}],
|
|
462
|
+
"trapFocus": [{
|
|
463
|
+
"onTrapFocusChange": 0
|
|
293
464
|
}]
|
|
294
465
|
}; }
|
|
295
466
|
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { r as registerInstance, c as createEvent, h, a as getElement } from './index-DJkaRtbb.js';
|
|
2
|
-
import { R as RichText } from './index-
|
|
2
|
+
import { R as RichText } from './index-CgyOJePd.js';
|
|
3
3
|
import { g as getRichTextStrings } from './richTextI18n-xnrKkNWQ.js';
|
|
4
4
|
import { E as EchoGuard, p as parseEditorValue, a as applyExternalValue, b as parseFeatures, c as buildOutput, s as syncToolbarEditor, d as syncImageLayouts } from './rich-text-host-BmdKHBZP.js';
|
|
5
|
-
import './pagination-
|
|
5
|
+
import './pagination-BzrIQtrk.js';
|
|
6
6
|
import './purify.es-B2QLgWrz.js';
|
|
7
7
|
import './toolbar-config-CRxTFT_z.js';
|
|
8
8
|
|
|
@@ -133,7 +133,7 @@ const CoRichTextViewer = class {
|
|
|
133
133
|
// JSON mode — lazily import the serializer (pulls Tiptap on demand only).
|
|
134
134
|
try {
|
|
135
135
|
const doc = JSON.parse(this.value);
|
|
136
|
-
const rt = await import('./index-
|
|
136
|
+
const rt = await import('./index-CgyOJePd.js').then(function (n) { return n.R; });
|
|
137
137
|
this.html = rt.jsonToHtml(doc, this.preset);
|
|
138
138
|
}
|
|
139
139
|
catch (_a) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { r as registerInstance, c as createEvent, h, a as getElement } from './index-DJkaRtbb.js';
|
|
2
2
|
|
|
3
|
-
const coToggleButtonCss = () => `:host{display:inline-flex;--co-toggle-button-radius:var(--co-border-radius-sm)}:host([size='l']){--co-toggle-button-radius:var(--co-border-radius-lg)}:host([size='m']){--co-toggle-button-radius:var(--co-border-radius-sm)}:host([size='s']){--co-toggle-button-radius:var(--co-border-radius-xs)}:host([size='xs']){--co-toggle-button-radius:var(--co-border-radius-xs)}.co-toggle-button{display:inline-flex;width:var(--co-toggle-button-width, auto);align-items:center;justify-content:center;gap:var(--co-spacing-sm2);border:1px solid var(--co-semantic-border-subtle);border-top-left-radius:var(--co-tbr-tl, var(--co-toggle-button-radius));border-top-right-radius:var(--co-tbr-tr, var(--co-toggle-button-radius));border-bottom-right-radius:var(--co-tbr-br, var(--co-toggle-button-radius));border-bottom-left-radius:var(--co-tbr-bl, var(--co-toggle-button-radius));background:color-mix(in srgb, var(--co-semantic-surface-secondary) 35%, transparent);-webkit-backdrop-filter:var(--co-glass-filter, blur(var(--co-glass-blur)) saturate(var(--co-glass-saturate)));backdrop-filter:var(--co-glass-filter, blur(var(--co-glass-blur)) saturate(var(--co-glass-saturate)));color:var(--co-semantic-text-default);font-family:var(--co-font-family-primary);font-weight:500;cursor:pointer;transition:background var(--co-motion-duration-fast) var(--co-motion-ease-out), border-color var(--co-motion-duration-fast) var(--co-motion-ease-out), color var(--co-motion-duration-fast) var(--co-motion-ease-out);white-space:nowrap;box-sizing:border-box;line-height:1}.co-toggle-button--l{height:48px;padding:0 var(--co-spacing-lg);font-size:var(--co-font-size-16)}.co-toggle-button--m{height:40px;padding:0 var(--co-spacing-md);font-size:var(--co-font-size-14)}.co-toggle-button--s{height:32px;padding:0 var(--co-spacing-sm2);font-size:var(--co-font-size-14)}.co-toggle-button--xs{height:24px;padding:0 var(--co-spacing-sm);font-size:var(--co-font-size-12)}.co-toggle-button--icon-only.co-toggle-button--l{width:48px;padding:0}.co-toggle-button--icon-only.co-toggle-button--m{width:40px;padding:0}.co-toggle-button--icon-only.co-toggle-button--s{width:32px;padding:0}.co-toggle-button--icon-only.co-toggle-button--xs{width:24px;padding:0}.co-toggle-button:hover:not(:disabled){background:var(--co-semantic-surface-hover)}.co-toggle-button--selected{background:var(--co-color-base-negro, #1f1c1b);color:var(--co-color-base-blanco, #fff);border-color:var(--co-color-base-negro, #1f1c1b)}.co-toggle-button--selected:hover:not(:disabled){background:var(--co-color-gray-800, #0a0a0a);border-color:var(--co-color-gray-800, #0a0a0a)}.co-toggle-button--disabled{opacity:0.4;cursor:not-allowed}.co-toggle-button:focus-visible{outline:2px solid var(--co-semantic-text-default);outline-offset:-3px}.co-toggle-button--selected:focus-visible{outline-color:currentColor}.co-toggle-button__label{line-height:1}@supports not (background: color-mix(in srgb, red, transparent)){.co-toggle-button{background:var(--co-semantic-surface-secondary)}}:host([variant='track']) .co-toggle-button{height:var(--co-toggle-pill-height, 30px);border-radius:var(--co-toggle-pill-radius, 8px);border-color:transparent;background:transparent;color:var(--co-semantic-text-secondary);box-shadow:none;padding:0 12px;-webkit-backdrop-filter:none;backdrop-filter:none}:host([variant='track']) .co-toggle-button.co-toggle-button--icon-only{width:34px;padding:0}:host([variant='track']) .co-toggle-button:hover:not(:disabled){background:var(--co-semantic-surface-hover);color:var(--co-semantic-text-default)}:host([variant='track']) .co-toggle-button--selected{background:var(--co-semantic-surface-page);color:var(--co-semantic-text-default);border-color:var(--co-toggle-pill-border, var(--co-semantic-border-default));box-shadow:var(--co-toggle-pill-shadow, var(--co-shadow-sm, 0 1px 2px 0 rgba(26, 26, 26, 0.04)))}:host([variant='track']) .co-toggle-button--selected:hover:not(:disabled){background:var(--co-semantic-surface-page);border-color:var(--co-toggle-pill-border, var(--co-semantic-border-default))}:host([variant='track'][size='xs']) .co-toggle-button{height:var(--co-toggle-pill-height, 20px);border-radius:var(--co-toggle-pill-radius, var(--co-border-radius-xxs))}:host([variant='track'][size='xs']) .co-toggle-button:not(.co-toggle-button--selected){color:var(--co-semantic-text-default)}:host([variant='track'][size='xs']) .co-toggle-button.co-toggle-button--icon-only{width:20px}:host([variant='track'][size='xs']) .co-toggle-button--selected{box-shadow:var(--co-toggle-pill-shadow, none)}:host([variant='soft']) .co-toggle-button{height:24px;border-radius:var(--co-border-radius-xxs);border-color:transparent;background:var(--co-semantic-surface-control, #f6f6f6);color:var(--co-semantic-text-default);font-size:var(--co-font-size-12);font-weight:var(--co-font-weight-regular);padding:0 calc(var(--co-spacing-sm2) - 1px);gap:var(--co-spacing-sm2);-webkit-backdrop-filter:none;backdrop-filter:none}:host([variant='soft']) .co-toggle-button:hover:not(:disabled){background:var(--co-semantic-surface-control, #f6f6f6)}:host([variant='soft']) .co-toggle-button--selected{background:var(--co-color-celeste-100);color:var(--co-color-primary-azul);border-color:transparent}:host([variant='soft']) .co-toggle-button--selected:hover:not(:disabled){background:var(--co-color-celeste-100)}`;
|
|
3
|
+
const coToggleButtonCss = () => `:host{display:inline-flex;--co-toggle-button-radius:var(--co-border-radius-sm)}:host([size='l']){--co-toggle-button-radius:var(--co-border-radius-lg)}:host([size='m']){--co-toggle-button-radius:var(--co-border-radius-sm)}:host([size='s']){--co-toggle-button-radius:var(--co-border-radius-xs)}:host([size='xs']){--co-toggle-button-radius:var(--co-border-radius-xs)}.co-toggle-button{display:inline-flex;width:var(--co-toggle-button-width, auto);align-items:center;justify-content:center;gap:var(--co-spacing-sm2);border:1px solid var(--co-semantic-border-subtle);border-top-left-radius:var(--co-tbr-tl, var(--co-toggle-button-radius));border-top-right-radius:var(--co-tbr-tr, var(--co-toggle-button-radius));border-bottom-right-radius:var(--co-tbr-br, var(--co-toggle-button-radius));border-bottom-left-radius:var(--co-tbr-bl, var(--co-toggle-button-radius));background:color-mix(in srgb, var(--co-semantic-surface-secondary) 35%, transparent);-webkit-backdrop-filter:var(--co-glass-filter, blur(var(--co-glass-blur)) saturate(var(--co-glass-saturate)));backdrop-filter:var(--co-glass-filter, blur(var(--co-glass-blur)) saturate(var(--co-glass-saturate)));color:var(--co-toggle-button-color, var(--co-semantic-text-default));font-family:var(--co-font-family-primary);font-weight:500;cursor:pointer;transition:background var(--co-motion-duration-fast) var(--co-motion-ease-out), border-color var(--co-motion-duration-fast) var(--co-motion-ease-out), color var(--co-motion-duration-fast) var(--co-motion-ease-out);white-space:nowrap;box-sizing:border-box;line-height:1}.co-toggle-button--l{height:48px;padding:0 var(--co-spacing-lg);font-size:var(--co-toggle-button-font-size, var(--co-font-size-16))}.co-toggle-button--m{height:40px;padding:0 var(--co-spacing-md);font-size:var(--co-toggle-button-font-size, var(--co-font-size-14))}.co-toggle-button--s{height:32px;padding:0 var(--co-spacing-sm2);font-size:var(--co-toggle-button-font-size, var(--co-font-size-14))}.co-toggle-button--xs{height:24px;padding:0 var(--co-spacing-sm);font-size:var(--co-toggle-button-font-size, var(--co-font-size-12))}.co-toggle-button--icon-only.co-toggle-button--l{width:48px;padding:0}.co-toggle-button--icon-only.co-toggle-button--m{width:40px;padding:0}.co-toggle-button--icon-only.co-toggle-button--s{width:32px;padding:0}.co-toggle-button--icon-only.co-toggle-button--xs{width:24px;padding:0}.co-toggle-button:hover:not(:disabled){background:var(--co-semantic-surface-hover)}.co-toggle-button--selected{background:var(--co-color-base-negro, #1f1c1b);color:var(--co-toggle-button-color-selected, var(--co-color-base-blanco, #fff));border-color:var(--co-color-base-negro, #1f1c1b)}.co-toggle-button--selected:hover:not(:disabled){background:var(--co-color-gray-800, #0a0a0a);border-color:var(--co-color-gray-800, #0a0a0a)}.co-toggle-button--disabled{opacity:0.4;cursor:not-allowed}.co-toggle-button:focus-visible{outline:2px solid var(--co-semantic-text-default);outline-offset:-3px}.co-toggle-button--selected:focus-visible{outline-color:currentColor}.co-toggle-button__label{line-height:1}@supports not (background: color-mix(in srgb, red, transparent)){.co-toggle-button{background:var(--co-semantic-surface-secondary)}}:host([variant='track']) .co-toggle-button{height:var(--co-toggle-pill-height, 30px);border-radius:var(--co-toggle-pill-radius, 8px);border-color:transparent;background:transparent;color:var(--co-toggle-button-color, var(--co-semantic-text-secondary));box-shadow:none;padding:0 12px;-webkit-backdrop-filter:none;backdrop-filter:none}:host([variant='track']) .co-toggle-button.co-toggle-button--icon-only{width:34px;padding:0}:host([variant='track']) .co-toggle-button:hover:not(:disabled){background:var(--co-semantic-surface-hover);color:var(--co-toggle-button-color-hover, var(--co-semantic-text-default))}:host([variant='track']) .co-toggle-button--selected{background:var(--co-semantic-surface-page);color:var(--co-toggle-button-color-selected, var(--co-semantic-text-default));border-color:var(--co-toggle-pill-border, var(--co-semantic-border-default));box-shadow:var(--co-toggle-pill-shadow, var(--co-shadow-sm, 0 1px 2px 0 rgba(26, 26, 26, 0.04)))}:host([variant='track']) .co-toggle-button--selected:hover:not(:disabled){background:var(--co-semantic-surface-page);color:var(--co-toggle-button-color-selected, var(--co-semantic-text-default));border-color:var(--co-toggle-pill-border, var(--co-semantic-border-default))}:host([variant='track'][size='xs']) .co-toggle-button{height:var(--co-toggle-pill-height, 20px);border-radius:var(--co-toggle-pill-radius, var(--co-border-radius-xxs))}:host([variant='track'][size='xs']) .co-toggle-button:not(.co-toggle-button--selected){color:var(--co-toggle-button-color, var(--co-semantic-text-default))}:host([variant='track'][size='xs']) .co-toggle-button:not(.co-toggle-button--selected):hover:not(:disabled){color:var(--co-toggle-button-color-hover, var(--co-semantic-text-default))}:host([variant='track'][size='xs']) .co-toggle-button.co-toggle-button--icon-only{width:20px}:host([variant='track'][size='xs']) .co-toggle-button--selected{box-shadow:var(--co-toggle-pill-shadow, none)}:host([variant='soft']) .co-toggle-button{height:24px;border-radius:var(--co-border-radius-xxs);border-color:transparent;background:var(--co-semantic-surface-control, #f6f6f6);color:var(--co-toggle-button-color, var(--co-semantic-text-default));font-size:var(--co-font-size-12);font-weight:var(--co-font-weight-regular);padding:0 calc(var(--co-spacing-sm2) - 1px);gap:var(--co-spacing-sm2);-webkit-backdrop-filter:none;backdrop-filter:none}:host([variant='soft']) .co-toggle-button:hover:not(:disabled){background:var(--co-semantic-surface-control, #f6f6f6)}:host([variant='soft']) .co-toggle-button--selected{background:var(--co-color-celeste-100);color:var(--co-toggle-button-color-selected, var(--co-color-primary-azul));border-color:transparent}:host([variant='soft']) .co-toggle-button--selected:hover:not(:disabled){background:var(--co-color-celeste-100)}`;
|
|
4
4
|
|
|
5
5
|
/** Tallas que entiende este botón. El grupo puede traer una fuera de esta
|
|
6
6
|
* lista (el host usa `<co-toggle-button-group size="sm">`): nunca se adopta. */
|