@wrrdev/fenix-ui 1.1.15 → 1.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/components/pagination/pagination.d.ts +3 -0
- package/dist/components/pagination/pagination.d.ts.map +1 -1
- package/dist/components/pagination/pagination.js +19 -9
- package/dist/components/pagination/pagination.js.map +1 -1
- package/dist/components/table/table.d.ts.map +1 -1
- package/dist/components/table/table.js +20 -3
- package/dist/components/table/table.js.map +1 -1
- package/dist/core/page-range.d.ts +31 -0
- package/dist/core/page-range.d.ts.map +1 -0
- package/dist/core/page-range.js +41 -0
- package/dist/core/page-range.js.map +1 -0
- package/dist/docs/componentes/table.doc.d.ts.map +1 -1
- package/dist/fenix-ui.umd.min.js +139 -115
- package/dist/fenix-ui4.esm.js +171 -109
- package/dist/fenix-ui4.esm.js.map +1 -1
- package/package.json +1 -1
package/dist/fenix-ui4.esm.js
CHANGED
|
@@ -3337,6 +3337,43 @@ function defineFxRadio() {
|
|
|
3337
3337
|
return defineElement("fx-radio", FxRadio);
|
|
3338
3338
|
}
|
|
3339
3339
|
defineFxRadio();
|
|
3340
|
+
function toInt(value, fallback) {
|
|
3341
|
+
return Number.isFinite(value) ? Math.trunc(value) : fallback;
|
|
3342
|
+
}
|
|
3343
|
+
function range(start, end) {
|
|
3344
|
+
const out = [];
|
|
3345
|
+
for (let p = start; p <= end; p++) out.push(p);
|
|
3346
|
+
return out;
|
|
3347
|
+
}
|
|
3348
|
+
function pageRange(current, count, options = {}) {
|
|
3349
|
+
const pages = Math.max(0, toInt(count, 0));
|
|
3350
|
+
if (pages === 0) return [];
|
|
3351
|
+
const boundaries = Math.max(0, toInt(options.boundaries ?? 1, 1));
|
|
3352
|
+
const siblings = Math.max(0, toInt(options.siblings ?? 1, 1));
|
|
3353
|
+
const page = Math.min(Math.max(1, toInt(current, 1)), pages);
|
|
3354
|
+
if (pages <= boundaries * 2 + siblings * 2 + 3) return range(1, pages);
|
|
3355
|
+
const startPages = range(1, Math.min(boundaries, pages));
|
|
3356
|
+
const endPages = range(
|
|
3357
|
+
Math.max(pages - boundaries + 1, boundaries + 1),
|
|
3358
|
+
pages
|
|
3359
|
+
);
|
|
3360
|
+
const siblingsStart = Math.max(
|
|
3361
|
+
Math.min(page - siblings, pages - boundaries - siblings * 2 - 1),
|
|
3362
|
+
boundaries + 2
|
|
3363
|
+
);
|
|
3364
|
+
const siblingsEnd = Math.min(
|
|
3365
|
+
Math.max(page + siblings, boundaries + siblings * 2 + 2),
|
|
3366
|
+
endPages.length > 0 ? endPages[0] - 2 : pages - 1
|
|
3367
|
+
);
|
|
3368
|
+
const items = [...startPages];
|
|
3369
|
+
if (siblingsStart > boundaries + 2) items.push("ellipsis");
|
|
3370
|
+
else if (boundaries + 1 < pages - boundaries) items.push(boundaries + 1);
|
|
3371
|
+
items.push(...range(siblingsStart, siblingsEnd));
|
|
3372
|
+
if (siblingsEnd < pages - boundaries - 1) items.push("ellipsis");
|
|
3373
|
+
else if (pages - boundaries > boundaries) items.push(pages - boundaries);
|
|
3374
|
+
items.push(...endPages);
|
|
3375
|
+
return items;
|
|
3376
|
+
}
|
|
3340
3377
|
const LOCALE = "pt-BR";
|
|
3341
3378
|
const PIPES = {
|
|
3342
3379
|
/** Formata como moeda brasileira (R$). */
|
|
@@ -3991,12 +4028,15 @@ const _FxTable = class _FxTable extends FxElement {
|
|
|
3991
4028
|
const bodyHtml = rows.length ? rows.map(
|
|
3992
4029
|
(row, i) => `<tr part="row" data-index="${i}">${cols.map((c) => `<td part="cell" style="text-align:${c.align}">${this.cellHtml(c, row)}</td>`).join("")}</tr>`
|
|
3993
4030
|
).join("") : `<tr><td class="empty" colspan="${cols.length || 1}">${esc(this.getAttr("empty-message", "Nenhum registro encontrado"))}</td></tr>`;
|
|
4031
|
+
const pageButtons = pageRange(this.page + 1, pages).map(
|
|
4032
|
+
(item) => item === "ellipsis" ? `<span class="ellipsis" part="ellipsis" aria-hidden="true">…</span>` : `<button type="button" class="pg-btn" part="page" data-pg="${item - 1}"${item === this.page + 1 ? ' aria-current="page"' : ""}>${item}</button>`
|
|
4033
|
+
).join("");
|
|
3994
4034
|
const pagerHtml = !paginated ? "" : `
|
|
3995
4035
|
<div class="pager" part="pager">
|
|
3996
4036
|
<span class="info">Página ${this.page + 1} de ${pages} · ${total} registros</span>
|
|
3997
4037
|
<button type="button" class="pg-btn" part="first" aria-label="Primeira página" data-pg="first" ${this.page === 0 ? "disabled" : ""}>${fenixIconHtml("first_page")}</button>
|
|
3998
4038
|
<button type="button" class="pg-btn" part="prev" aria-label="Página anterior" data-pg="prev" ${this.page === 0 ? "disabled" : ""}>${fenixIconHtml("navigate_before")}</button>
|
|
3999
|
-
${
|
|
4039
|
+
${pageButtons}
|
|
4000
4040
|
<button type="button" class="pg-btn" part="next" aria-label="Próxima página" data-pg="next" ${this.page >= pages - 1 ? "disabled" : ""}>${fenixIconHtml("navigate_next")}</button>
|
|
4001
4041
|
<button type="button" class="pg-btn" part="last" aria-label="Última página" data-pg="last" ${this.page >= pages - 1 ? "disabled" : ""}>${fenixIconHtml("last_page")}</button>
|
|
4002
4042
|
<label class="info">${esc("Por página:")}
|
|
@@ -4352,7 +4392,7 @@ _FxTable.styles = css`
|
|
|
4352
4392
|
.pg-btn .fx-icon {
|
|
4353
4393
|
font-size: calc(var(--fx-font-size) - 1px);
|
|
4354
4394
|
}
|
|
4355
|
-
.pg-btn:hover:not(:disabled):not([aria-current="
|
|
4395
|
+
.pg-btn:hover:not(:disabled):not([aria-current="page"]) {
|
|
4356
4396
|
border-color: var(--fx-color-primary);
|
|
4357
4397
|
color: var(--fx-color-primary);
|
|
4358
4398
|
}
|
|
@@ -4360,12 +4400,25 @@ _FxTable.styles = css`
|
|
|
4360
4400
|
opacity: 0.5;
|
|
4361
4401
|
cursor: not-allowed;
|
|
4362
4402
|
}
|
|
4363
|
-
.pg-btn[aria-current="
|
|
4403
|
+
.pg-btn[aria-current="page"] {
|
|
4364
4404
|
background: var(--fx-color-primary);
|
|
4365
4405
|
border-color: var(--fx-color-primary);
|
|
4366
4406
|
color: #fff;
|
|
4367
4407
|
font-weight: var(--fx-font-weight);
|
|
4368
4408
|
}
|
|
4409
|
+
/* Elipse da janela de páginas (1 … 499 [500] 501 … 1000): ocupa o
|
|
4410
|
+
mesmo espaço de um botão para o rodapé não "pular" ao navegar,
|
|
4411
|
+
mas não é clicável. */
|
|
4412
|
+
.pager .ellipsis {
|
|
4413
|
+
display: inline-flex;
|
|
4414
|
+
align-items: center;
|
|
4415
|
+
justify-content: center;
|
|
4416
|
+
min-width: var(--fx-size-sm);
|
|
4417
|
+
height: var(--fx-size-sm);
|
|
4418
|
+
color: var(--fx-text-muted);
|
|
4419
|
+
font-size: calc(var(--fx-font-size) - 2px);
|
|
4420
|
+
user-select: none;
|
|
4421
|
+
}
|
|
4369
4422
|
/* O seletor "Por página" só mostra números, então não pode herdar a
|
|
4370
4423
|
largura padrão do <fx-select> (200px / 180px em size="sm"), que
|
|
4371
4424
|
deixava o rodapé da paginação desproporcional. O limite tem que ser
|
|
@@ -6118,10 +6171,10 @@ function rootOf(editor) {
|
|
|
6118
6171
|
const root = editor.getRootNode();
|
|
6119
6172
|
return typeof ShadowRoot !== "undefined" && root instanceof ShadowRoot ? root : document;
|
|
6120
6173
|
}
|
|
6121
|
-
function isRangeInside(editor,
|
|
6122
|
-
if (!
|
|
6123
|
-
const start =
|
|
6124
|
-
const end =
|
|
6174
|
+
function isRangeInside(editor, range2) {
|
|
6175
|
+
if (!range2) return false;
|
|
6176
|
+
const start = range2.startContainer;
|
|
6177
|
+
const end = range2.endContainer;
|
|
6125
6178
|
return editor.contains(start) && editor.contains(end);
|
|
6126
6179
|
}
|
|
6127
6180
|
function readSelectionRange(root) {
|
|
@@ -6132,10 +6185,10 @@ function readSelectionRange(root) {
|
|
|
6132
6185
|
const ranges = selection.getComposedRanges({ shadowRoots: [root] });
|
|
6133
6186
|
const first = ranges[0];
|
|
6134
6187
|
if (first) {
|
|
6135
|
-
const
|
|
6136
|
-
|
|
6137
|
-
|
|
6138
|
-
return
|
|
6188
|
+
const range2 = document.createRange();
|
|
6189
|
+
range2.setStart(first.startContainer, first.startOffset);
|
|
6190
|
+
range2.setEnd(first.endContainer, first.endOffset);
|
|
6191
|
+
return range2;
|
|
6139
6192
|
}
|
|
6140
6193
|
} catch {
|
|
6141
6194
|
}
|
|
@@ -6143,41 +6196,41 @@ function readSelectionRange(root) {
|
|
|
6143
6196
|
return selection.rangeCount > 0 ? selection.getRangeAt(0) : null;
|
|
6144
6197
|
}
|
|
6145
6198
|
function getRange(editor, fallback) {
|
|
6146
|
-
const
|
|
6147
|
-
if (isRangeInside(editor,
|
|
6199
|
+
const range2 = readSelectionRange(rootOf(editor));
|
|
6200
|
+
if (isRangeInside(editor, range2)) return range2;
|
|
6148
6201
|
if (isRangeInside(editor, fallback ?? null)) return fallback ?? null;
|
|
6149
6202
|
return null;
|
|
6150
6203
|
}
|
|
6151
6204
|
function saveRange(editor) {
|
|
6152
|
-
const
|
|
6153
|
-
return
|
|
6205
|
+
const range2 = getRange(editor);
|
|
6206
|
+
return range2 ? range2.cloneRange() : null;
|
|
6154
6207
|
}
|
|
6155
|
-
function restoreRange(editor,
|
|
6156
|
-
if (!
|
|
6208
|
+
function restoreRange(editor, range2) {
|
|
6209
|
+
if (!range2 || !isRangeInside(editor, range2)) return;
|
|
6157
6210
|
editor.focus({ preventScroll: true });
|
|
6158
6211
|
const selection = document.getSelection();
|
|
6159
6212
|
if (!selection) return;
|
|
6160
6213
|
selection.removeAllRanges();
|
|
6161
|
-
selection.addRange(
|
|
6214
|
+
selection.addRange(range2);
|
|
6162
6215
|
}
|
|
6163
6216
|
function placeCaretAtEnd(editor) {
|
|
6164
|
-
const
|
|
6165
|
-
|
|
6166
|
-
|
|
6217
|
+
const range2 = document.createRange();
|
|
6218
|
+
range2.selectNodeContents(editor);
|
|
6219
|
+
range2.collapse(false);
|
|
6167
6220
|
const selection = document.getSelection();
|
|
6168
6221
|
if (!selection) return;
|
|
6169
6222
|
selection.removeAllRanges();
|
|
6170
|
-
selection.addRange(
|
|
6223
|
+
selection.addRange(range2);
|
|
6171
6224
|
}
|
|
6172
|
-
function getBlock(editor,
|
|
6173
|
-
const active =
|
|
6225
|
+
function getBlock(editor, range2) {
|
|
6226
|
+
const active = range2 ?? getRange(editor);
|
|
6174
6227
|
if (!active) return null;
|
|
6175
6228
|
const node = active.startContainer;
|
|
6176
6229
|
const el = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
|
|
6177
6230
|
const block = el?.closest(BLOCK_SELECTOR) ?? null;
|
|
6178
6231
|
return block && editor.contains(block) ? block : null;
|
|
6179
6232
|
}
|
|
6180
|
-
function getSelectedBlocks(editor,
|
|
6233
|
+
function getSelectedBlocks(editor, range2) {
|
|
6181
6234
|
const active = getRange(editor);
|
|
6182
6235
|
if (!active) return [];
|
|
6183
6236
|
if (active.collapsed) {
|
|
@@ -6197,11 +6250,11 @@ function closestInEditor(editor, node, selector) {
|
|
|
6197
6250
|
const match = el?.closest(selector) ?? null;
|
|
6198
6251
|
return match && editor.contains(match) ? match : null;
|
|
6199
6252
|
}
|
|
6200
|
-
function setSelection(
|
|
6253
|
+
function setSelection(range2) {
|
|
6201
6254
|
const selection = document.getSelection();
|
|
6202
6255
|
if (!selection) return;
|
|
6203
6256
|
selection.removeAllRanges();
|
|
6204
|
-
selection.addRange(
|
|
6257
|
+
selection.addRange(range2);
|
|
6205
6258
|
}
|
|
6206
6259
|
function nativeExec(command, value) {
|
|
6207
6260
|
const exec = document.execCommand;
|
|
@@ -6214,16 +6267,16 @@ function nativeExec(command, value) {
|
|
|
6214
6267
|
}
|
|
6215
6268
|
function insertHtml(editor, html) {
|
|
6216
6269
|
if (nativeExec("insertHTML", html)) return true;
|
|
6217
|
-
const
|
|
6218
|
-
if (!
|
|
6270
|
+
const range2 = getRange(editor);
|
|
6271
|
+
if (!range2) {
|
|
6219
6272
|
editor.insertAdjacentHTML("beforeend", html);
|
|
6220
6273
|
placeCaretAtEnd(editor);
|
|
6221
6274
|
return true;
|
|
6222
6275
|
}
|
|
6223
|
-
|
|
6224
|
-
const fragment =
|
|
6276
|
+
range2.deleteContents();
|
|
6277
|
+
const fragment = range2.createContextualFragment(html);
|
|
6225
6278
|
const last = fragment.lastChild;
|
|
6226
|
-
|
|
6279
|
+
range2.insertNode(fragment);
|
|
6227
6280
|
if (last) {
|
|
6228
6281
|
const next = document.createRange();
|
|
6229
6282
|
next.setStartAfter(last);
|
|
@@ -6239,12 +6292,12 @@ function unwrap(el) {
|
|
|
6239
6292
|
el.remove();
|
|
6240
6293
|
}
|
|
6241
6294
|
function wrapSelection(editor, tag) {
|
|
6242
|
-
const
|
|
6243
|
-
if (!
|
|
6295
|
+
const range2 = getRange(editor);
|
|
6296
|
+
if (!range2) return false;
|
|
6244
6297
|
const el = document.createElement(tag);
|
|
6245
|
-
if (
|
|
6298
|
+
if (range2.collapsed) {
|
|
6246
6299
|
el.appendChild(document.createTextNode(""));
|
|
6247
|
-
|
|
6300
|
+
range2.insertNode(el);
|
|
6248
6301
|
const caret = document.createRange();
|
|
6249
6302
|
caret.setStart(el.firstChild ?? el, 1);
|
|
6250
6303
|
caret.collapse(true);
|
|
@@ -6252,10 +6305,10 @@ function wrapSelection(editor, tag) {
|
|
|
6252
6305
|
return true;
|
|
6253
6306
|
}
|
|
6254
6307
|
try {
|
|
6255
|
-
|
|
6308
|
+
range2.surroundContents(el);
|
|
6256
6309
|
} catch {
|
|
6257
|
-
el.appendChild(
|
|
6258
|
-
|
|
6310
|
+
el.appendChild(range2.extractContents());
|
|
6311
|
+
range2.insertNode(el);
|
|
6259
6312
|
}
|
|
6260
6313
|
return true;
|
|
6261
6314
|
}
|
|
@@ -6271,9 +6324,9 @@ function toggleInline(editor, tag) {
|
|
|
6271
6324
|
};
|
|
6272
6325
|
const nativeCommand = nativeMap[tag];
|
|
6273
6326
|
if (nativeCommand && nativeExec(nativeCommand)) return true;
|
|
6274
|
-
const
|
|
6275
|
-
if (!
|
|
6276
|
-
const current = (
|
|
6327
|
+
const range2 = getRange(editor);
|
|
6328
|
+
if (!range2) return false;
|
|
6329
|
+
const current = (range2.startContainer.nodeType === Node.ELEMENT_NODE ? range2.startContainer : range2.startContainer.parentElement)?.closest(tag);
|
|
6277
6330
|
if (current && editor.contains(current)) {
|
|
6278
6331
|
unwrap(current);
|
|
6279
6332
|
return true;
|
|
@@ -6322,31 +6375,31 @@ function toggleList(editor, ordered) {
|
|
|
6322
6375
|
list.appendChild(li);
|
|
6323
6376
|
block.remove();
|
|
6324
6377
|
}
|
|
6325
|
-
const
|
|
6326
|
-
|
|
6327
|
-
|
|
6328
|
-
setSelection(
|
|
6378
|
+
const range2 = document.createRange();
|
|
6379
|
+
range2.selectNodeContents(list.lastElementChild ?? list);
|
|
6380
|
+
range2.collapse(false);
|
|
6381
|
+
setSelection(range2);
|
|
6329
6382
|
return true;
|
|
6330
6383
|
}
|
|
6331
6384
|
function removeFormat(editor) {
|
|
6332
6385
|
if (nativeExec("removeFormat")) return true;
|
|
6333
|
-
const
|
|
6334
|
-
if (!
|
|
6335
|
-
const root =
|
|
6386
|
+
const range2 = getRange(editor);
|
|
6387
|
+
if (!range2) return false;
|
|
6388
|
+
const root = range2.commonAncestorContainer;
|
|
6336
6389
|
const container = root.nodeType === Node.ELEMENT_NODE ? root : root.parentElement;
|
|
6337
6390
|
if (!container) return false;
|
|
6338
6391
|
const tags = ["strong", "b", "em", "i", "u", "s", "strike", "span", "mark", "code", "sub", "sup"];
|
|
6339
6392
|
for (const el of Array.from(container.querySelectorAll(tags.join(",")))) {
|
|
6340
|
-
if (
|
|
6393
|
+
if (range2.intersectsNode(el)) unwrap(el);
|
|
6341
6394
|
}
|
|
6342
6395
|
return true;
|
|
6343
6396
|
}
|
|
6344
6397
|
const linkHtml = (href, label, target) => `<a href="${escapeAttr(href)}" target="${target}" rel="noopener noreferrer">${escapeText(label)}</a>`;
|
|
6345
6398
|
function applyLink(editor, href, text, target = "_blank") {
|
|
6346
6399
|
const label = text?.trim() || href;
|
|
6347
|
-
const
|
|
6348
|
-
if (!
|
|
6349
|
-
const anchor = (
|
|
6400
|
+
const range2 = getRange(editor);
|
|
6401
|
+
if (!range2) return insertHtml(editor, linkHtml(href, label, target));
|
|
6402
|
+
const anchor = (range2.startContainer.nodeType === Node.ELEMENT_NODE ? range2.startContainer : range2.startContainer.parentElement)?.closest("a");
|
|
6350
6403
|
if (anchor && editor.contains(anchor)) {
|
|
6351
6404
|
anchor.setAttribute("href", href);
|
|
6352
6405
|
anchor.setAttribute("target", target);
|
|
@@ -6354,9 +6407,9 @@ function applyLink(editor, href, text, target = "_blank") {
|
|
|
6354
6407
|
if (text && text !== anchor.textContent) anchor.textContent = text;
|
|
6355
6408
|
return true;
|
|
6356
6409
|
}
|
|
6357
|
-
if (!
|
|
6410
|
+
if (!range2.collapsed) {
|
|
6358
6411
|
if (nativeExec("createLink", href)) {
|
|
6359
|
-
const created = (
|
|
6412
|
+
const created = (range2.startContainer.nodeType === Node.ELEMENT_NODE ? range2.startContainer : range2.startContainer.parentElement)?.closest("a");
|
|
6360
6413
|
created?.setAttribute("target", target);
|
|
6361
6414
|
created?.setAttribute("rel", "noopener noreferrer");
|
|
6362
6415
|
return true;
|
|
@@ -6366,10 +6419,10 @@ function applyLink(editor, href, text, target = "_blank") {
|
|
|
6366
6419
|
el.setAttribute("target", target);
|
|
6367
6420
|
el.setAttribute("rel", "noopener noreferrer");
|
|
6368
6421
|
try {
|
|
6369
|
-
|
|
6422
|
+
range2.surroundContents(el);
|
|
6370
6423
|
} catch {
|
|
6371
|
-
el.appendChild(
|
|
6372
|
-
|
|
6424
|
+
el.appendChild(range2.extractContents());
|
|
6425
|
+
range2.insertNode(el);
|
|
6373
6426
|
}
|
|
6374
6427
|
return true;
|
|
6375
6428
|
}
|
|
@@ -6377,9 +6430,9 @@ function applyLink(editor, href, text, target = "_blank") {
|
|
|
6377
6430
|
}
|
|
6378
6431
|
function unlink(editor) {
|
|
6379
6432
|
if (nativeExec("unlink")) return true;
|
|
6380
|
-
const
|
|
6381
|
-
if (!
|
|
6382
|
-
const anchor = (
|
|
6433
|
+
const range2 = getRange(editor);
|
|
6434
|
+
if (!range2) return false;
|
|
6435
|
+
const anchor = (range2.startContainer.nodeType === Node.ELEMENT_NODE ? range2.startContainer : range2.startContainer.parentElement)?.closest("a");
|
|
6383
6436
|
if (anchor && editor.contains(anchor)) {
|
|
6384
6437
|
unwrap(anchor);
|
|
6385
6438
|
return true;
|
|
@@ -6447,10 +6500,10 @@ function cellPosition(table, cell) {
|
|
|
6447
6500
|
}
|
|
6448
6501
|
return null;
|
|
6449
6502
|
}
|
|
6450
|
-
function selectedCells(table,
|
|
6503
|
+
function selectedCells(table, range2) {
|
|
6451
6504
|
return Array.from(table.querySelectorAll("td,th")).filter((cell) => {
|
|
6452
6505
|
try {
|
|
6453
|
-
return
|
|
6506
|
+
return range2.intersectsNode(cell);
|
|
6454
6507
|
} catch {
|
|
6455
6508
|
return false;
|
|
6456
6509
|
}
|
|
@@ -6462,8 +6515,8 @@ function copyCellAttributes(from, to) {
|
|
|
6462
6515
|
to.setAttribute(attr.name, attr.value);
|
|
6463
6516
|
}
|
|
6464
6517
|
}
|
|
6465
|
-
function mergeSelectedCells(table,
|
|
6466
|
-
const cells = selectedCells(table,
|
|
6518
|
+
function mergeSelectedCells(table, range2) {
|
|
6519
|
+
const cells = selectedCells(table, range2);
|
|
6467
6520
|
if (cells.length < 2) return null;
|
|
6468
6521
|
const { matrix } = tableMatrix(table);
|
|
6469
6522
|
const positions = cells.map((cell) => ({ cell, position: cellPosition(table, cell) })).filter((item) => Boolean(item.position));
|
|
@@ -6846,9 +6899,9 @@ const _FxEditor = class _FxEditor extends FxFormElement {
|
|
|
6846
6899
|
mergeCells() {
|
|
6847
6900
|
const table = __privateMethod(this, _FxEditor_instances, currentTable_fn).call(this);
|
|
6848
6901
|
const editor = this.editor;
|
|
6849
|
-
const
|
|
6850
|
-
if (!table || !
|
|
6851
|
-
const merged = mergeSelectedCells(table,
|
|
6902
|
+
const range2 = editor ? getRange(editor, __privateGet(this, _lastRange)) : null;
|
|
6903
|
+
if (!table || !range2) return false;
|
|
6904
|
+
const merged = mergeSelectedCells(table, range2);
|
|
6852
6905
|
if (!merged) return false;
|
|
6853
6906
|
placeCaretAtEnd(merged);
|
|
6854
6907
|
__privateMethod(this, _FxEditor_instances, afterCommand_fn).call(this);
|
|
@@ -6858,8 +6911,8 @@ const _FxEditor = class _FxEditor extends FxFormElement {
|
|
|
6858
6911
|
splitCell() {
|
|
6859
6912
|
const table = __privateMethod(this, _FxEditor_instances, currentTable_fn).call(this);
|
|
6860
6913
|
const editor = this.editor;
|
|
6861
|
-
const
|
|
6862
|
-
const cell = editor ? closestInEditor(editor,
|
|
6914
|
+
const range2 = editor ? getRange(editor, __privateGet(this, _lastRange)) : null;
|
|
6915
|
+
const cell = editor ? closestInEditor(editor, range2?.startContainer ?? null, "td,th") : null;
|
|
6863
6916
|
if (!table || !cell) return false;
|
|
6864
6917
|
const created = splitCell(table, cell);
|
|
6865
6918
|
if (!created.length) return false;
|
|
@@ -7119,8 +7172,8 @@ fits_fn = function(extra) {
|
|
|
7119
7172
|
const max = this.maxlength;
|
|
7120
7173
|
if (!max) return true;
|
|
7121
7174
|
const editor = this.editor;
|
|
7122
|
-
const
|
|
7123
|
-
const selected =
|
|
7175
|
+
const range2 = editor ? getRange(editor, __privateGet(this, _lastRange)) : null;
|
|
7176
|
+
const selected = range2 && !range2.collapsed ? range2.toString().length : 0;
|
|
7124
7177
|
return this.text.length - selected + extra <= max;
|
|
7125
7178
|
};
|
|
7126
7179
|
limitError_fn = function() {
|
|
@@ -7243,9 +7296,9 @@ bindGlobalSelection_fn = function() {
|
|
|
7243
7296
|
const handler = () => {
|
|
7244
7297
|
const editor = this.editor;
|
|
7245
7298
|
if (!editor) return;
|
|
7246
|
-
const
|
|
7247
|
-
if (!
|
|
7248
|
-
__privateSet(this, _lastRange,
|
|
7299
|
+
const range2 = getRange(editor, __privateGet(this, _lastRange));
|
|
7300
|
+
if (!range2) return;
|
|
7301
|
+
__privateSet(this, _lastRange, range2.cloneRange());
|
|
7249
7302
|
cancelAnimationFrame(__privateGet(this, _selectionRaf));
|
|
7250
7303
|
__privateSet(this, _selectionRaf, requestAnimationFrame(() => __privateMethod(this, _FxEditor_instances, updateToolbar_fn).call(this)));
|
|
7251
7304
|
};
|
|
@@ -7370,8 +7423,8 @@ renderToolbar_fn = function() {
|
|
|
7370
7423
|
updateToolbar_fn = function() {
|
|
7371
7424
|
const editor = this.editor;
|
|
7372
7425
|
if (!editor) return;
|
|
7373
|
-
const
|
|
7374
|
-
if (!
|
|
7426
|
+
const range2 = getRange(editor, __privateGet(this, _lastRange));
|
|
7427
|
+
if (!range2) return;
|
|
7375
7428
|
const setActive = (cmd, active) => {
|
|
7376
7429
|
const button = this.root.querySelector(`[data-cmd="${cmd}"]`);
|
|
7377
7430
|
if (!button) return;
|
|
@@ -7379,7 +7432,7 @@ updateToolbar_fn = function() {
|
|
|
7379
7432
|
button.setAttribute("aria-pressed", String(active));
|
|
7380
7433
|
};
|
|
7381
7434
|
const ancestor = (selector) => {
|
|
7382
|
-
const node =
|
|
7435
|
+
const node = range2.startContainer;
|
|
7383
7436
|
const el = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
|
|
7384
7437
|
const match = el?.closest(selector);
|
|
7385
7438
|
return Boolean(match && editor.contains(match));
|
|
@@ -7391,7 +7444,7 @@ updateToolbar_fn = function() {
|
|
|
7391
7444
|
setActive("code", ancestor("code"));
|
|
7392
7445
|
setActive("insertUnorderedList", ancestor("ul"));
|
|
7393
7446
|
setActive("insertOrderedList", ancestor("ol"));
|
|
7394
|
-
const block = getBlock(editor,
|
|
7447
|
+
const block = getBlock(editor, range2);
|
|
7395
7448
|
const blockTag = block?.tagName.toLowerCase() ?? "p";
|
|
7396
7449
|
const blockSelect = this.root.querySelector("[data-block]");
|
|
7397
7450
|
if (blockSelect) {
|
|
@@ -7635,9 +7688,9 @@ handleKeydown_fn = function(event) {
|
|
|
7635
7688
|
tabInTable_fn = function(backwards) {
|
|
7636
7689
|
const editor = this.editor;
|
|
7637
7690
|
if (!editor) return false;
|
|
7638
|
-
const
|
|
7639
|
-
if (!
|
|
7640
|
-
const cell = closestInEditor(editor,
|
|
7691
|
+
const range2 = getRange(editor, __privateGet(this, _lastRange));
|
|
7692
|
+
if (!range2) return false;
|
|
7693
|
+
const cell = closestInEditor(editor, range2.startContainer, "td,th");
|
|
7641
7694
|
const table = cell?.closest("table");
|
|
7642
7695
|
if (!cell || !table) return false;
|
|
7643
7696
|
const cells = Array.from(table.querySelectorAll("td,th"));
|
|
@@ -7807,14 +7860,14 @@ openLinkDialog_fn = async function(existing) {
|
|
|
7807
7860
|
const editor = this.editor;
|
|
7808
7861
|
if (!editor) return;
|
|
7809
7862
|
if (existing) __privateMethod(this, _FxEditor_instances, selectAnchor_fn).call(this, existing);
|
|
7810
|
-
let
|
|
7811
|
-
if (!
|
|
7863
|
+
let range2 = getRange(editor, __privateGet(this, _lastRange));
|
|
7864
|
+
if (!range2) {
|
|
7812
7865
|
placeCaretAtEnd(editor);
|
|
7813
|
-
|
|
7814
|
-
__privateSet(this, _lastRange,
|
|
7866
|
+
range2 = getRange(editor);
|
|
7867
|
+
__privateSet(this, _lastRange, range2?.cloneRange() ?? null);
|
|
7815
7868
|
}
|
|
7816
|
-
const anchor = existing ?? closestInEditor(editor,
|
|
7817
|
-
const selected =
|
|
7869
|
+
const anchor = existing ?? closestInEditor(editor, range2?.startContainer ?? null, "a");
|
|
7870
|
+
const selected = range2 && !range2.collapsed ? range2.toString() : anchor?.textContent ?? "";
|
|
7818
7871
|
const result = await __privateMethod(this, _FxEditor_instances, openDialog_fn).call(this, "Link", [
|
|
7819
7872
|
{ name: "url", label: "URL", type: "url", value: anchor?.getAttribute("href") ?? "", placeholder: "https://..." },
|
|
7820
7873
|
{ name: "text", label: "Texto (quando não há seleção)", value: selected, placeholder: "Texto do link" },
|
|
@@ -8037,13 +8090,13 @@ selectAnchor_fn = function(anchor) {
|
|
|
8037
8090
|
const editor = this.editor;
|
|
8038
8091
|
if (!editor) return;
|
|
8039
8092
|
editor.focus({ preventScroll: true });
|
|
8040
|
-
const
|
|
8041
|
-
|
|
8093
|
+
const range2 = document.createRange();
|
|
8094
|
+
range2.selectNodeContents(anchor);
|
|
8042
8095
|
const selection = document.getSelection();
|
|
8043
8096
|
if (!selection) return;
|
|
8044
8097
|
selection.removeAllRanges();
|
|
8045
|
-
selection.addRange(
|
|
8046
|
-
__privateSet(this, _lastRange,
|
|
8098
|
+
selection.addRange(range2);
|
|
8099
|
+
__privateSet(this, _lastRange, range2.cloneRange());
|
|
8047
8100
|
};
|
|
8048
8101
|
handleLinkOverlayClick_fn = function(event) {
|
|
8049
8102
|
const action = event.target.closest("[data-link-action]");
|
|
@@ -8314,19 +8367,19 @@ hidePanel_fn = function() {
|
|
|
8314
8367
|
currentTable_fn = function() {
|
|
8315
8368
|
const editor = this.editor;
|
|
8316
8369
|
if (!editor) return null;
|
|
8317
|
-
const
|
|
8318
|
-
return closestInEditor(editor,
|
|
8370
|
+
const range2 = getRange(editor, __privateGet(this, _lastRange));
|
|
8371
|
+
return closestInEditor(editor, range2?.startContainer ?? null, "table");
|
|
8319
8372
|
};
|
|
8320
8373
|
tableAction_fn = function(action) {
|
|
8321
8374
|
const table = __privateMethod(this, _FxEditor_instances, currentTable_fn).call(this);
|
|
8322
8375
|
if (!table) return;
|
|
8323
8376
|
const editor = this.editor;
|
|
8324
|
-
const
|
|
8325
|
-
const cell = editor ? closestInEditor(editor,
|
|
8377
|
+
const range2 = editor ? getRange(editor, __privateGet(this, _lastRange)) : null;
|
|
8378
|
+
const cell = editor ? closestInEditor(editor, range2?.startContainer ?? null, "td,th") : null;
|
|
8326
8379
|
const row = cell?.parentElement;
|
|
8327
8380
|
if (action === "merge-cells") {
|
|
8328
|
-
if (!
|
|
8329
|
-
const merged = mergeSelectedCells(table,
|
|
8381
|
+
if (!range2) return;
|
|
8382
|
+
const merged = mergeSelectedCells(table, range2);
|
|
8330
8383
|
if (!merged) return;
|
|
8331
8384
|
placeCaretAtEnd(merged);
|
|
8332
8385
|
__privateMethod(this, _FxEditor_instances, afterCommand_fn).call(this);
|
|
@@ -13101,17 +13154,16 @@ const _FxPagination = class _FxPagination extends FxElement {
|
|
|
13101
13154
|
const pages = this.pages;
|
|
13102
13155
|
const current = Math.min(Math.max(1, this.page), pages);
|
|
13103
13156
|
const opts = (this.getAttr("rows-options", "5,10,20,50") || "").split(",").map((s) => s.trim()).filter(Boolean);
|
|
13104
|
-
const
|
|
13105
|
-
|
|
13106
|
-
|
|
13157
|
+
const pageButtons = pageRange(current, pages).map(
|
|
13158
|
+
(item) => item === "ellipsis" ? `<span class="ellipsis" part="ellipsis" aria-hidden="true">…</span>` : `<button type="button" class="nav ${item === current ? "active" : ""}" part="page" data-go="${item}"${item === current ? ' aria-current="page"' : ""}>${item}</button>`
|
|
13159
|
+
).join("");
|
|
13160
|
+
const from = (current - 1) * this.rows + 1;
|
|
13107
13161
|
const to = Math.min(current * this.rows, this.total);
|
|
13108
13162
|
this.setTemplate(`
|
|
13109
13163
|
<span class="info">${this.total ? `${from}-${to} de ${this.total}` : "0 itens"}</span>
|
|
13110
13164
|
<button type="button" class="nav" part="first" aria-label="Primeira página" data-go="1" ${current <= 1 ? "disabled" : ""}>${fenixIconHtml("first_page")}</button>
|
|
13111
13165
|
<button type="button" class="nav" part="prev" aria-label="Página anterior" data-go="${current - 1}" ${current <= 1 ? "disabled" : ""}>${fenixIconHtml("navigate_before")}</button>
|
|
13112
|
-
${
|
|
13113
|
-
${window_.map((p) => `<button type="button" class="nav ${p === current ? "active" : ""}" data-go="${p}">${p}</button>`).join("")}
|
|
13114
|
-
${window_[window_.length - 1] !== pages && pages > 5 ? `<button type="button" class="nav" data-go="${pages}">${pages}</button>` : ""}
|
|
13166
|
+
${pageButtons}
|
|
13115
13167
|
<button type="button" class="nav" part="next" aria-label="Próxima página" data-go="${current + 1}" ${current >= pages ? "disabled" : ""}>${fenixIconHtml("navigate_next")}</button>
|
|
13116
13168
|
<button type="button" class="nav" part="last" aria-label="Última página" data-go="${pages}" ${current >= pages ? "disabled" : ""}>${fenixIconHtml("last_page")}</button>
|
|
13117
13169
|
${opts.length ? `
|
|
@@ -13119,9 +13171,6 @@ const _FxPagination = class _FxPagination extends FxElement {
|
|
|
13119
13171
|
${opts.map((o) => `<option value="${esc(o)}">${esc(o)}</option>`).join("")}
|
|
13120
13172
|
</fx-select>` : ""}
|
|
13121
13173
|
`);
|
|
13122
|
-
function total0(page, rows) {
|
|
13123
|
-
return (page - 1) * rows + 1;
|
|
13124
|
-
}
|
|
13125
13174
|
this.root.querySelectorAll(".nav[data-go]").forEach((btn) => {
|
|
13126
13175
|
btn.addEventListener("click", () => {
|
|
13127
13176
|
const target = Number(btn.dataset.go);
|
|
@@ -13153,6 +13202,7 @@ _FxPagination.styles = css`
|
|
|
13153
13202
|
:host {
|
|
13154
13203
|
display: flex;
|
|
13155
13204
|
align-items: center;
|
|
13205
|
+
flex-wrap: wrap;
|
|
13156
13206
|
gap: var(--fx-space-sm);
|
|
13157
13207
|
font-family: var(--fx-font-family);
|
|
13158
13208
|
font-size: var(--fx-font-size);
|
|
@@ -13190,6 +13240,18 @@ _FxPagination.styles = css`
|
|
|
13190
13240
|
color: #fff;
|
|
13191
13241
|
font-weight: 600;
|
|
13192
13242
|
}
|
|
13243
|
+
/* Elipse entre a janela de páginas e as bordas: ocupa o mesmo espaço de
|
|
13244
|
+
um botão (para o rodapé não "pular" ao navegar) mas não é clicável. */
|
|
13245
|
+
.ellipsis {
|
|
13246
|
+
display: inline-flex;
|
|
13247
|
+
align-items: center;
|
|
13248
|
+
justify-content: center;
|
|
13249
|
+
min-width: var(--fx-size-sm);
|
|
13250
|
+
height: var(--fx-size-sm);
|
|
13251
|
+
color: var(--fx-text-muted);
|
|
13252
|
+
font-size: calc(var(--fx-font-size) - 2px);
|
|
13253
|
+
user-select: none;
|
|
13254
|
+
}
|
|
13193
13255
|
.info { color: var(--fx-text-muted); font-size: calc(var(--fx-font-size) - 2px); }
|
|
13194
13256
|
fx-select { vertical-align: middle; }
|
|
13195
13257
|
fx-select::part(trigger) {
|
|
@@ -13525,8 +13587,8 @@ const _FxKnob = class _FxKnob extends FxFormElement {
|
|
|
13525
13587
|
const min = this.min;
|
|
13526
13588
|
const max = this.max;
|
|
13527
13589
|
const value = this.clampValue(this.value);
|
|
13528
|
-
const
|
|
13529
|
-
const pct =
|
|
13590
|
+
const range2 = max - min;
|
|
13591
|
+
const pct = range2 > 0 ? (value - min) / range2 : 0;
|
|
13530
13592
|
const sizeNum = this.getSizeNum();
|
|
13531
13593
|
const strokeW = this.strokeWidth;
|
|
13532
13594
|
const radius = (sizeNum - strokeW) / 2;
|