@grafloria/element 0.4.30 → 0.4.31
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/package.json
CHANGED
|
@@ -761,57 +761,157 @@ export function createDashboardHandle(ctx) {
|
|
|
761
761
|
new RegisterWidgetCommand(born, 'register'),
|
|
762
762
|
]),
|
|
763
763
|
];
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
const
|
|
764
|
+
return { move, collapse: remaining.length > 0 ? [] : collapseOf(boardId) };
|
|
765
|
+
},
|
|
766
|
+
joinTargets: [...ctx.layoutOf.keys()].filter((id) => { var _a, _b; return id !== containerId && id !== pageId && ((_a = ctx.layoutOf.get(id)) !== null && _a !== void 0 ? _a : (_b = specById.get(id)) === null || _b === void 0 ? void 0 : _b.layout) === 'tabs' && !!model.getGroup(id) && !insidePage(id); }),
|
|
767
|
+
dropIndex: (targetId, cx, cy) => {
|
|
768
|
+
const strip = ctx.tabStrips.get(targetId);
|
|
769
|
+
const n = liveCount(targetId);
|
|
770
|
+
if (!strip)
|
|
771
|
+
return n;
|
|
772
|
+
const r = strip.getBoundingClientRect();
|
|
773
|
+
if (r.width === 0 || cx < r.left || cx > r.right || cy < r.top || cy > r.bottom)
|
|
774
|
+
return n;
|
|
775
|
+
const rtl = strip.getAttribute('dir') === 'rtl';
|
|
776
|
+
let i = 0;
|
|
777
|
+
for (const t of Array.from(strip.querySelectorAll('.axdb-tab'))) {
|
|
778
|
+
const tr = t.getBoundingClientRect();
|
|
779
|
+
const mid = tr.left + tr.width / 2;
|
|
780
|
+
if (rtl ? cx < mid : cx > mid)
|
|
781
|
+
i++;
|
|
782
|
+
else
|
|
783
|
+
break;
|
|
784
|
+
}
|
|
785
|
+
return i;
|
|
786
|
+
},
|
|
787
|
+
markDrop: (targetId, index) => {
|
|
788
|
+
for (const [id, el] of ctx.tabStrips) {
|
|
789
|
+
const on = id === targetId;
|
|
790
|
+
el.classList.toggle('axdb-tabs--drop', on);
|
|
791
|
+
const tabs = Array.from(el.querySelectorAll('.axdb-tab'));
|
|
792
|
+
tabs.forEach((t, i) => t.classList.toggle('axdb-tab--drop-before', on && index !== null && i === index));
|
|
793
|
+
el.classList.toggle('axdb-tabs--drop-end', on && index !== null && index >= tabs.length);
|
|
794
|
+
}
|
|
795
|
+
},
|
|
796
|
+
join: (targetId, index, boardId) => {
|
|
797
|
+
var _a;
|
|
798
|
+
const target = (_a = ctx.boardGroups.get(targetId)) !== null && _a !== void 0 ? _a : model.getGroup(targetId);
|
|
799
|
+
const targetSpec = specById.get(targetId);
|
|
800
|
+
if (!target || !targetSpec)
|
|
801
|
+
return { move: [], collapse: [] };
|
|
802
|
+
const prevActive = ctx.activeTab.get(targetId);
|
|
803
|
+
const cwOf = (g) => { var _a; return ((_a = g.getMetadata('containerWidget')) !== null && _a !== void 0 ? _a : {}); };
|
|
804
|
+
let slot = -1;
|
|
805
|
+
const joined = {
|
|
770
806
|
register: () => {
|
|
771
807
|
var _a;
|
|
772
|
-
|
|
773
|
-
if (
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
if (
|
|
782
|
-
|
|
808
|
+
viewOfWidget.set(pageId, targetId);
|
|
809
|
+
if (fromSpec === null || fromSpec === void 0 ? void 0 : fromSpec.widgets) {
|
|
810
|
+
const i = fromSpec.widgets.findIndex((p) => p.id === pageId);
|
|
811
|
+
if (i >= 0) {
|
|
812
|
+
slot = i;
|
|
813
|
+
fromSpec.widgets.splice(i, 1);
|
|
814
|
+
}
|
|
815
|
+
}
|
|
816
|
+
targetSpec.widgets = (_a = targetSpec.widgets) !== null && _a !== void 0 ? _a : [];
|
|
817
|
+
if (!targetSpec.widgets.some((p) => p.id === pageId)) {
|
|
818
|
+
targetSpec.widgets.splice(Math.max(0, Math.min(index, targetSpec.widgets.length)), 0, pageSpec);
|
|
783
819
|
}
|
|
784
|
-
|
|
820
|
+
ctx.boardWidgets.set(targetId, targetSpec.widgets);
|
|
821
|
+
// The moved tab is the one showing, as it is in VS Code.
|
|
822
|
+
ctx.activeTab.set(targetId, pageId);
|
|
823
|
+
targetSpec.active = pageId;
|
|
824
|
+
target.setMetadata('containerWidget', Object.assign(Object.assign({}, cwOf(target)), { active: pageId }));
|
|
785
825
|
},
|
|
786
826
|
unregister: () => {
|
|
787
|
-
|
|
788
|
-
(
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
}
|
|
827
|
+
viewOfWidget.set(pageId, containerId);
|
|
828
|
+
if (targetSpec.widgets) {
|
|
829
|
+
const i = targetSpec.widgets.findIndex((p) => p.id === pageId);
|
|
830
|
+
if (i >= 0)
|
|
831
|
+
targetSpec.widgets.splice(i, 1);
|
|
832
|
+
}
|
|
833
|
+
if ((fromSpec === null || fromSpec === void 0 ? void 0 : fromSpec.widgets) && !fromSpec.widgets.some((p) => p.id === pageId)) {
|
|
834
|
+
fromSpec.widgets.splice(slot < 0 ? fromSpec.widgets.length : Math.min(slot, fromSpec.widgets.length), 0, pageSpec);
|
|
835
|
+
}
|
|
836
|
+
if (prevActive) {
|
|
837
|
+
ctx.activeTab.set(targetId, prevActive);
|
|
838
|
+
targetSpec.active = prevActive;
|
|
839
|
+
target.setMetadata('containerWidget', Object.assign(Object.assign({}, cwOf(target)), { active: prevActive }));
|
|
800
840
|
}
|
|
801
841
|
},
|
|
802
842
|
};
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
new
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
],
|
|
812
|
-
};
|
|
843
|
+
const move = [
|
|
844
|
+
new SequenceCommand('Move tab', [
|
|
845
|
+
new RemoveFromGroupCommand(containerId, pageId),
|
|
846
|
+
new AddToGroupCommand(targetId, pageId),
|
|
847
|
+
new RegisterWidgetCommand(joined, 'register'),
|
|
848
|
+
]),
|
|
849
|
+
];
|
|
850
|
+
return { move, collapse: remaining.length > 0 ? [] : collapseOf(boardId) };
|
|
813
851
|
},
|
|
814
852
|
};
|
|
853
|
+
/** A tab container nested inside the page being moved cannot be its target. */
|
|
854
|
+
function insidePage(id) {
|
|
855
|
+
let cur = model.getGroup(id);
|
|
856
|
+
for (let i = 0; cur && i < 32; i++) {
|
|
857
|
+
if (cur.id === pageId)
|
|
858
|
+
return true;
|
|
859
|
+
cur = cur.parentGroupId ? model.getGroup(cur.parentGroupId) : undefined;
|
|
860
|
+
}
|
|
861
|
+
return false;
|
|
862
|
+
}
|
|
863
|
+
function liveCount(id) {
|
|
864
|
+
var _a, _b;
|
|
865
|
+
return [...((_b = (_a = model.getGroup(id)) === null || _a === void 0 ? void 0 : _a.members) !== null && _b !== void 0 ? _b : [])].filter((m) => !!model.getGroup(m)).length;
|
|
866
|
+
}
|
|
867
|
+
/**
|
|
868
|
+
* The last page left: the container closes. Its registry goes FIRST so
|
|
869
|
+
* that on undo it comes back AFTER the group and its slab do.
|
|
870
|
+
*/
|
|
871
|
+
function collapseOf(boardId) {
|
|
872
|
+
let fromSlot = -1;
|
|
873
|
+
const gone = {
|
|
874
|
+
register: () => {
|
|
875
|
+
var _a;
|
|
876
|
+
const live = model.getGroup(containerId);
|
|
877
|
+
if (!live)
|
|
878
|
+
return;
|
|
879
|
+
ctx.boardGroups.set(containerId, live);
|
|
880
|
+
ctx.layoutOf.set(containerId, 'tabs');
|
|
881
|
+
ctx.viewOfBoard.set(containerId, viewId);
|
|
882
|
+
if (fromSpec)
|
|
883
|
+
specById.set(containerId, fromSpec);
|
|
884
|
+
const arr = ctx.boardWidgets.get(boardId);
|
|
885
|
+
if (arr && fromSpec && !arr.some((w) => w.id === containerId)) {
|
|
886
|
+
arr.splice(fromSlot < 0 ? arr.length : Math.min(fromSlot, arr.length), 0, fromSpec);
|
|
887
|
+
}
|
|
888
|
+
(_a = ctx.attachTabsContainer) === null || _a === void 0 ? void 0 : _a.call(ctx, containerId);
|
|
889
|
+
},
|
|
890
|
+
unregister: () => {
|
|
891
|
+
var _a;
|
|
892
|
+
(_a = ctx.detachTabsContainer) === null || _a === void 0 ? void 0 : _a.call(ctx, containerId);
|
|
893
|
+
ctx.boardGroups.delete(containerId);
|
|
894
|
+
ctx.layoutOf.delete(containerId);
|
|
895
|
+
ctx.viewOfBoard.delete(containerId);
|
|
896
|
+
specById.delete(containerId);
|
|
897
|
+
const arr = ctx.boardWidgets.get(boardId);
|
|
898
|
+
if (arr) {
|
|
899
|
+
const i = arr.findIndex((w) => w.id === containerId);
|
|
900
|
+
if (i >= 0) {
|
|
901
|
+
fromSlot = i;
|
|
902
|
+
arr.splice(i, 1);
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
},
|
|
906
|
+
};
|
|
907
|
+
return [
|
|
908
|
+
new SequenceCommand('Close empty tab container', [
|
|
909
|
+
new RegisterWidgetCommand(gone, 'unregister'),
|
|
910
|
+
new RemoveFromGroupCommand(boardId, containerId),
|
|
911
|
+
new RemoveGroupCommand(containerId),
|
|
912
|
+
]),
|
|
913
|
+
];
|
|
914
|
+
}
|
|
815
915
|
};
|
|
816
916
|
/** Bookkeeping closures for one widget, shared by the add and remove
|
|
817
917
|
* commands (and applied synchronously by the handle — idempotent). */
|
|
@@ -538,6 +538,26 @@ export interface TearOutPlan {
|
|
|
538
538
|
move: Command[];
|
|
539
539
|
collapse: Command[];
|
|
540
540
|
};
|
|
541
|
+
/**
|
|
542
|
+
* The tab containers the page may JOIN instead of forming a group of its
|
|
543
|
+
* own — VS Code's editor dragged from one group into another. Every one it
|
|
544
|
+
* may legally enter (not the container it left, none inside itself); the
|
|
545
|
+
* board hit-tests them against the pointer, and a release over one joins.
|
|
546
|
+
*/
|
|
547
|
+
joinTargets: string[];
|
|
548
|
+
/** The tab index a release at this CLIENT point means for `targetId`: over the strip, between the tabs there; over the body, the end. */
|
|
549
|
+
dropIndex(targetId: string, clientX: number, clientY: number): number;
|
|
550
|
+
/** Paint (or, with null, clear) the insertion mark on `targetId`'s strip. */
|
|
551
|
+
markDrop(targetId: string | null, index: number | null): void;
|
|
552
|
+
/**
|
|
553
|
+
* The commands for joining `targetId` at `index`: the page becomes its tab
|
|
554
|
+
* — and the active one — and the container it left closes when it was the
|
|
555
|
+
* last page. No cell is taken on any board.
|
|
556
|
+
*/
|
|
557
|
+
join(targetId: string, index: number, boardId: string): {
|
|
558
|
+
move: Command[];
|
|
559
|
+
collapse: Command[];
|
|
560
|
+
};
|
|
541
561
|
}
|
|
542
562
|
/** A torn-out page never arrives shorter than this: a strip with no room under it is not a group. */
|
|
543
563
|
export declare const TEAR_OUT_MIN_ROWS = 2;
|
|
@@ -559,6 +579,16 @@ interface AdoptedLeg {
|
|
|
559
579
|
x: number;
|
|
560
580
|
y: number;
|
|
561
581
|
}): void;
|
|
582
|
+
/**
|
|
583
|
+
* Take the tile OFF the board while the pointer is somewhere the board is
|
|
584
|
+
* not the target (over a group the page will join instead); the tiles it
|
|
585
|
+
* displaced come home. `enter` puts it back at the pointer.
|
|
586
|
+
*/
|
|
587
|
+
leave(): void;
|
|
588
|
+
enter(world: {
|
|
589
|
+
x: number;
|
|
590
|
+
y: number;
|
|
591
|
+
}): void;
|
|
562
592
|
/** Undo the adoption: target board back to its pre-entry layout. */
|
|
563
593
|
abort(): void;
|
|
564
594
|
/**
|
|
@@ -2314,8 +2314,29 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
2314
2314
|
project();
|
|
2315
2315
|
syncPlaceholder();
|
|
2316
2316
|
},
|
|
2317
|
+
leave: () => {
|
|
2318
|
+
if (!engine.getItem(node.id))
|
|
2319
|
+
return;
|
|
2320
|
+
engine.remove(node.id); // displaced tiles come home (gesture memory)
|
|
2321
|
+
lastWant = null;
|
|
2322
|
+
project();
|
|
2323
|
+
syncPlaceholder();
|
|
2324
|
+
},
|
|
2325
|
+
enter: (w) => {
|
|
2326
|
+
if (!engine.getItem(node.id) && !engine.add({ id: node.id, x: 0, y: engine.rows(), w: span.w, h: hNatural }))
|
|
2327
|
+
return;
|
|
2328
|
+
const item = engine.getItem(node.id);
|
|
2329
|
+
if (!item)
|
|
2330
|
+
return;
|
|
2331
|
+
const cell = wantedCell(w.x, w.y, item.w, opts.fit === 'shrink' ? hNatural : item.h);
|
|
2332
|
+
lastWant = cell;
|
|
2333
|
+
place(cell, item.w);
|
|
2334
|
+
project();
|
|
2335
|
+
syncPlaceholder();
|
|
2336
|
+
},
|
|
2317
2337
|
abort: () => {
|
|
2318
|
-
engine.
|
|
2338
|
+
if (engine.getItem(node.id))
|
|
2339
|
+
engine.remove(node.id);
|
|
2319
2340
|
engine.cancelGesture(); // pre-entry layout, memory cleared
|
|
2320
2341
|
adoptedGhostId = null;
|
|
2321
2342
|
disarmGlideSoon();
|
|
@@ -2920,6 +2941,48 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
2920
2941
|
chip.className = 'axdb-drag-chip axdb-tab-chip';
|
|
2921
2942
|
chip.textContent = plan.label;
|
|
2922
2943
|
doc.body.appendChild(chip);
|
|
2944
|
+
// Over ANOTHER tab container the page joins it instead of taking a cell:
|
|
2945
|
+
// the tile leaves the board (its displaced tiles come home), the target's
|
|
2946
|
+
// frame lights up and its strip marks where the tab will go.
|
|
2947
|
+
const layer = htmlLayer();
|
|
2948
|
+
const targets = plan.joinTargets
|
|
2949
|
+
.map((id) => diagram.getGroup(id))
|
|
2950
|
+
.filter((g) => !!g && g.id !== fromGroupId);
|
|
2951
|
+
const targetAt = (wx, wy) => { var _a; return (_a = targets.find((t) => worldInsideGroup(t, wx, wy))) !== null && _a !== void 0 ? _a : null; };
|
|
2952
|
+
let over = null;
|
|
2953
|
+
let joinEl = null;
|
|
2954
|
+
const showJoin = (g) => {
|
|
2955
|
+
if (!layer)
|
|
2956
|
+
return;
|
|
2957
|
+
if (!joinEl) {
|
|
2958
|
+
joinEl = doc.createElement('div');
|
|
2959
|
+
joinEl.className = 'axdb-join';
|
|
2960
|
+
layer.prepend(joinEl);
|
|
2961
|
+
}
|
|
2962
|
+
const sz = sizeOf(g);
|
|
2963
|
+
joinEl.style.left = `${g.position.x}px`;
|
|
2964
|
+
joinEl.style.top = `${g.position.y}px`;
|
|
2965
|
+
joinEl.style.width = `${sz.width}px`;
|
|
2966
|
+
joinEl.style.height = `${sz.height}px`;
|
|
2967
|
+
};
|
|
2968
|
+
const hideJoin = () => {
|
|
2969
|
+
joinEl === null || joinEl === void 0 ? void 0 : joinEl.remove();
|
|
2970
|
+
joinEl = null;
|
|
2971
|
+
plan.markDrop(null, null);
|
|
2972
|
+
};
|
|
2973
|
+
const setOver = (g, world) => {
|
|
2974
|
+
if (g === over)
|
|
2975
|
+
return;
|
|
2976
|
+
over = g;
|
|
2977
|
+
if (g) {
|
|
2978
|
+
leg.leave();
|
|
2979
|
+
showJoin(g);
|
|
2980
|
+
}
|
|
2981
|
+
else {
|
|
2982
|
+
hideJoin();
|
|
2983
|
+
leg.enter(world);
|
|
2984
|
+
}
|
|
2985
|
+
};
|
|
2923
2986
|
const moveChip = (cx, cy) => {
|
|
2924
2987
|
chip.style.left = `${cx + 6}px`;
|
|
2925
2988
|
chip.style.top = `${cy + 6}px`;
|
|
@@ -2941,27 +3004,48 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
2941
3004
|
moveChip(e.clientX, e.clientY);
|
|
2942
3005
|
const world = toWorld(e.clientX, e.clientY);
|
|
2943
3006
|
const home = worldInsideGroup(from, world.x, world.y);
|
|
3007
|
+
const target = home ? null : targetAt(world.x, world.y);
|
|
3008
|
+
setOver(target, world);
|
|
2944
3009
|
// Over its own container it goes home: a tab dragged around its own
|
|
2945
3010
|
// strip must not tear itself out.
|
|
2946
|
-
chip.classList.toggle('axdb-out', home || !worldInsideBoardGrace(world.x, world.y));
|
|
2947
|
-
if (
|
|
3011
|
+
chip.classList.toggle('axdb-out', home || (!target && !worldInsideBoardGrace(world.x, world.y)));
|
|
3012
|
+
if (target)
|
|
3013
|
+
plan.markDrop(target.id, plan.dropIndex(target.id, e.clientX, e.clientY));
|
|
3014
|
+
else if (!home)
|
|
2948
3015
|
leg.move(world);
|
|
2949
3016
|
api.render();
|
|
2950
3017
|
};
|
|
2951
3018
|
const finish = (commit) => {
|
|
2952
|
-
var _a, _b;
|
|
3019
|
+
var _a, _b, _c;
|
|
2953
3020
|
detach();
|
|
2954
3021
|
chip.remove();
|
|
3022
|
+
hideJoin();
|
|
2955
3023
|
tearing = null;
|
|
2956
3024
|
if (disposed)
|
|
2957
3025
|
return;
|
|
2958
3026
|
const world = toWorld(last.x, last.y);
|
|
2959
3027
|
const home = worldInsideGroup(from, world.x, world.y);
|
|
3028
|
+
const target = commit && !home ? targetAt(world.x, world.y) : null;
|
|
3029
|
+
if (target) {
|
|
3030
|
+
// JOIN: no cell on this board — the leg is abandoned (its displaced
|
|
3031
|
+
// tiles are already home) and the page becomes the target's tab.
|
|
3032
|
+
const index = plan.dropIndex(target.id, last.x, last.y);
|
|
3033
|
+
leg.abort();
|
|
3034
|
+
const planned = plan.join(target.id, index, group.id);
|
|
3035
|
+
const collapse = planned.collapse.length > 0 ? [...planRemovalOf(fromGroupId), ...planned.collapse] : [];
|
|
3036
|
+
const changed = execute('Move tab', [...planned.move, ...collapse]);
|
|
3037
|
+
disarmGlideSoon();
|
|
3038
|
+
enforceBoardHeight();
|
|
3039
|
+
persistLayouts();
|
|
3040
|
+
api.renderNow();
|
|
3041
|
+
(_a = options.onGesture) === null || _a === void 0 ? void 0 : _a.call(options, { type: 'commit', kind: 'move', nodeId: pageId, changed });
|
|
3042
|
+
return;
|
|
3043
|
+
}
|
|
2960
3044
|
if (!commit || home || !worldInsideBoardGrace(world.x, world.y)) {
|
|
2961
3045
|
leg.abort();
|
|
2962
3046
|
disarmGlideSoon();
|
|
2963
3047
|
api.renderNow();
|
|
2964
|
-
(
|
|
3048
|
+
(_b = options.onGesture) === null || _b === void 0 ? void 0 : _b.call(options, { type: 'cancel', kind: 'move', nodeId: pageId, changed: false });
|
|
2965
3049
|
return;
|
|
2966
3050
|
}
|
|
2967
3051
|
const fin = leg.finalize();
|
|
@@ -2980,7 +3064,7 @@ export function bindDashboardGrid(api, group, options = {}) {
|
|
|
2980
3064
|
enforceBoardHeight();
|
|
2981
3065
|
persistLayouts();
|
|
2982
3066
|
api.renderNow();
|
|
2983
|
-
(
|
|
3067
|
+
(_c = options.onGesture) === null || _c === void 0 ? void 0 : _c.call(options, { type: 'commit', kind: 'move', nodeId: pageId, changed });
|
|
2984
3068
|
};
|
|
2985
3069
|
const onUp = () => finish(true);
|
|
2986
3070
|
const onCancel = () => finish(false);
|
|
@@ -132,6 +132,28 @@ const CSS = `
|
|
|
132
132
|
box-shadow: 0 0 0 1px rgba(236, 238, 244, .16);
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
|
+
/* A tab held over ANOTHER group: it will join that group, not the board. The
|
|
136
|
+
group's frame lights up, and its strip marks the slot the tab will take —
|
|
137
|
+
a bar before the tab it lands in front of, or after the last one. */
|
|
138
|
+
.grafloria-html-layer > .axdb-join {
|
|
139
|
+
position: absolute;
|
|
140
|
+
z-index: 3;
|
|
141
|
+
pointer-events: none;
|
|
142
|
+
box-sizing: border-box;
|
|
143
|
+
border: 2px dashed var(--axdb-accent, #3b52d9);
|
|
144
|
+
background: var(--axdb-accent-soft, rgba(59, 82, 217, .08));
|
|
145
|
+
border-radius: var(--axdb-rs-radius, 3px);
|
|
146
|
+
}
|
|
147
|
+
.axdb-tabs.axdb-tabs--drop { box-shadow: inset 0 -2px 0 var(--axdb-accent, #3b52d9); }
|
|
148
|
+
.axdb-tab.axdb-tab--drop-before { position: relative; }
|
|
149
|
+
.axdb-tab.axdb-tab--drop-before::before {
|
|
150
|
+
content: ""; position: absolute; left: -3px; top: 4px; bottom: 4px; width: 3px;
|
|
151
|
+
border-radius: 2px; background: var(--axdb-accent, #3b52d9);
|
|
152
|
+
}
|
|
153
|
+
.axdb-tabs.axdb-tabs--drop-end::after {
|
|
154
|
+
content: ""; display: inline-block; width: 3px; height: 18px; margin: 0 4px;
|
|
155
|
+
border-radius: 2px; background: var(--axdb-accent, #3b52d9); vertical-align: middle; align-self: center;
|
|
156
|
+
}
|
|
135
157
|
|
|
136
158
|
/* ===========================================================================
|
|
137
159
|
BUILT-IN WIDGET CARDS — what widgets.ts paints when a page writes no
|