@threadlabs/looma 0.22.3 → 0.22.4
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/components/ui-tooltip/ui-tooltip.html +27 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
- package/styles/ui-tooltip.css +26 -0
- package/vanilla/UiTooltip.js +13 -1
- package/vue/UiTooltip.d.ts +3 -1
- package/vue/UiTooltip.vue +27 -1
- package/vue/chunks/UiTooltip.js +3 -2
- package/vue/components.css +40 -19
- package/vue/editor/index.js +42 -20
package/package.json
CHANGED
package/styles/ui-tooltip.css
CHANGED
|
@@ -91,6 +91,29 @@
|
|
|
91
91
|
box-shadow: var(--_ui-tooltip-shadow, var(--ui-overlay-shadow, var(--ui-elevation-tooltip, var(--ui-shadow-md))));
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
+
/* A keyboard shortcut follows the label after a thin divider, smaller and quieter, as menus show
|
|
95
|
+
it. The label stays first in the description, so a screen reader hears the name, then the keys. */
|
|
96
|
+
.shortcut {
|
|
97
|
+
display: inline-flex;
|
|
98
|
+
align-items: center;
|
|
99
|
+
margin-inline-start: var(--ui-space-2);
|
|
100
|
+
padding-inline-start: var(--ui-space-2);
|
|
101
|
+
border-inline-start: 1px solid color-mix(in oklab, currentColor 28%, transparent);
|
|
102
|
+
color: color-mix(in oklab, currentColor 72%, transparent);
|
|
103
|
+
font-size: var(--ui-font-size-xs);
|
|
104
|
+
font-weight: var(--ui-font-normal);
|
|
105
|
+
white-space: nowrap;
|
|
106
|
+
vertical-align: baseline;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.shortcut:empty {
|
|
110
|
+
display: none;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.shortcut kbd {
|
|
114
|
+
font: inherit;
|
|
115
|
+
}
|
|
116
|
+
|
|
94
117
|
:scope[data-ui-tooltip-state~="inverse"] .surface {
|
|
95
118
|
--_tooltip-line: var(--_ui-tooltip-inverse-surface, var(--ui-text-primary));
|
|
96
119
|
background: var(--_ui-tooltip-inverse-surface, var(--ui-text-primary));
|
|
@@ -193,6 +216,9 @@
|
|
|
193
216
|
@scope ([data-component~="ui-tooltip"]) to ([data-component]) {
|
|
194
217
|
/* This component's hooks style the element they are set on, and never a nested one. */
|
|
195
218
|
|
|
219
|
+
/* A keyboard shortcut follows the label after a thin divider, smaller and quieter, as menus show
|
|
220
|
+
it. The label stays first in the description, so a screen reader hears the name, then the keys. */
|
|
221
|
+
|
|
196
222
|
/* A rotated square shares the surface fill and draws the two outward border edges. Its centre sits on
|
|
197
223
|
* the surface border line, so the fill covers that stretch of border and the outline runs unbroken. */
|
|
198
224
|
|
package/vanilla/UiTooltip.js
CHANGED
|
@@ -3,7 +3,7 @@ import { manageComponentLifecycle } from "@nextwebwg/html-next/runtime";
|
|
|
3
3
|
import * as controller from "../components/ui-tooltip/ui-tooltip.js";
|
|
4
4
|
import "../styles/ui-tooltip.css";
|
|
5
5
|
|
|
6
|
-
const definition = {...{"contract":{"tag":"ui-tooltip","props":{"for":{"type":"string","required":false,"target":{"attribute":"for"},"default":""},"hideDelay":{"type":"number","required":false,"target":{"attribute":"hidedelay"},"default":100},"inverse":{"type":"boolean","required":false,"target":{"attribute":"inverse"},"default":false},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"default":false},"placement":{"type":{"kind":"terminal","name":"keyword"},"values":["top","top-start","top-end","bottom","bottom-start","bottom-end","left","left-start","left-end","right","right-start","right-end"],"required":false,"target":{"attribute":"placement"},"default":"top"},"showDelay":{"type":"number","required":false,"target":{"attribute":"showdelay"},"default":500},"trigger":{"type":{"kind":"terminal","name":"keyword"},"values":["hover","click","focus"],"required":false,"target":{"attribute":"trigger"},"default":"hover"}}},"template":{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"role","value":"tooltip"},{"kind":"attribute","name":"hidden","expression":"not internalOpen","expressionPlan":{"source":"not internalOpen","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"internalOpen"}},"dependencies":["internalOpen"]}}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"surface"}],"children":[{"kind":"slot"}]}]},"declarations":[{"kind":"state","name":"internalOpen","type":"boolean","value":"false","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"event","name":"open","type":"object","shape":{"kind":"object","fields":[{"name":"open","type":{"kind":"terminal","name":"boolean"},"optional":false},{"name":"reason","type":{"kind":"constrained","base":{"kind":"terminal","name":"keyword"},"values":["action","programmatic","light-dismiss","escape"]},"optional":false},{"name":"trigger","type":{"kind":"constrained","base":{"kind":"terminal","name":"keyword"},"values":["keyboard","pointer","programmatic"]},"optional":false}],"open":false},"bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"close","type":"object","shape":{"kind":"object","fields":[{"name":"open","type":{"kind":"terminal","name":"boolean"},"optional":false},{"name":"reason","type":{"kind":"constrained","base":{"kind":"terminal","name":"keyword"},"values":["action","programmatic","light-dismiss","escape"]},"optional":false},{"name":"trigger","type":{"kind":"constrained","base":{"kind":"terminal","name":"keyword"},"values":["keyboard","pointer","programmatic"]},"optional":false}],"open":false},"bubbles":true,"composed":true,"cancelable":false}],"root":{"kind":"native","element":"span","choices":["span"]}},source:{file:import.meta.url},css:""};
|
|
6
|
+
const definition = {...{"contract":{"tag":"ui-tooltip","props":{"for":{"type":"string","required":false,"target":{"attribute":"for"},"default":""},"hideDelay":{"type":"number","required":false,"target":{"attribute":"hidedelay"},"default":100},"inverse":{"type":"boolean","required":false,"target":{"attribute":"inverse"},"default":false},"open":{"type":"boolean","required":false,"target":{"attribute":"open"},"default":false},"placement":{"type":{"kind":"terminal","name":"keyword"},"values":["top","top-start","top-end","bottom","bottom-start","bottom-end","left","left-start","left-end","right","right-start","right-end"],"required":false,"target":{"attribute":"placement"},"default":"top"},"showDelay":{"type":"number","required":false,"target":{"attribute":"showdelay"},"default":500},"trigger":{"type":{"kind":"terminal","name":"keyword"},"values":["hover","click","focus"],"required":false,"target":{"attribute":"trigger"},"default":"hover"}}},"template":{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"role","value":"tooltip"},{"kind":"attribute","name":"hidden","expression":"not internalOpen","expressionPlan":{"source":"not internalOpen","ast":{"kind":"unary","op":"not","operand":{"kind":"id","name":"internalOpen"}},"dependencies":["internalOpen"]}}],"children":[{"kind":"element","name":"div","attributes":[{"kind":"literal","name":"class","value":"surface"}],"children":[{"kind":"slot"},{"kind":"element","name":"span","attributes":[{"kind":"literal","name":"class","value":"shortcut"}],"children":[{"kind":"slot","fallback":[],"name":"shortcut"}]}]}]},"declarations":[{"kind":"state","name":"internalOpen","type":"boolean","value":"false","expression":{"source":"false","ast":{"kind":"literal","value":false},"dependencies":[]}},{"kind":"event","name":"open","type":"object","shape":{"kind":"object","fields":[{"name":"open","type":{"kind":"terminal","name":"boolean"},"optional":false},{"name":"reason","type":{"kind":"constrained","base":{"kind":"terminal","name":"keyword"},"values":["action","programmatic","light-dismiss","escape"]},"optional":false},{"name":"trigger","type":{"kind":"constrained","base":{"kind":"terminal","name":"keyword"},"values":["keyboard","pointer","programmatic"]},"optional":false}],"open":false},"bubbles":true,"composed":true,"cancelable":false},{"kind":"event","name":"close","type":"object","shape":{"kind":"object","fields":[{"name":"open","type":{"kind":"terminal","name":"boolean"},"optional":false},{"name":"reason","type":{"kind":"constrained","base":{"kind":"terminal","name":"keyword"},"values":["action","programmatic","light-dismiss","escape"]},"optional":false},{"name":"trigger","type":{"kind":"constrained","base":{"kind":"terminal","name":"keyword"},"values":["keyboard","pointer","programmatic"]},"optional":false}],"open":false},"bubbles":true,"composed":true,"cancelable":false}],"root":{"kind":"native","element":"span","choices":["span"]}},source:{file:import.meta.url},css:""};
|
|
7
7
|
|
|
8
8
|
export function createUiTooltip(options = {}) {
|
|
9
9
|
const { attributes = {}, children = [], slots = {}, ...componentProps } = options;
|
|
@@ -26,6 +26,18 @@ export function createUiTooltip(options = {}) {
|
|
|
26
26
|
}
|
|
27
27
|
} else {
|
|
28
28
|
}
|
|
29
|
+
const element1 = document.createElement("span");
|
|
30
|
+
element1.setAttribute("class", "shortcut");
|
|
31
|
+
if (slots["shortcut"] ?? [].length > 0) {
|
|
32
|
+
for (const child of slots["shortcut"] ?? []) {
|
|
33
|
+
const node = typeof child === "string" ? document.createTextNode(child) : child;
|
|
34
|
+
if (node.nodeType === 1) node.setAttribute("data-slotted", "");
|
|
35
|
+
projected.push([node, "shortcut"]);
|
|
36
|
+
element1.append(node);
|
|
37
|
+
}
|
|
38
|
+
} else {
|
|
39
|
+
}
|
|
40
|
+
element0.append(element1);
|
|
29
41
|
element.append(element0);
|
|
30
42
|
manageComponentLifecycle(element, definition, { props: componentProps, projected,
|
|
31
43
|
controller,
|
package/vue/UiTooltip.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import type { PropType } from 'vue';
|
|
2
|
-
declare var __VLS_1: {};
|
|
2
|
+
declare var __VLS_1: {}, __VLS_3: {};
|
|
3
3
|
type __VLS_Slots = {} & {
|
|
4
4
|
default?: (props: typeof __VLS_1) => any;
|
|
5
|
+
} & {
|
|
6
|
+
shortcut?: (props: typeof __VLS_3) => any;
|
|
5
7
|
};
|
|
6
8
|
declare const __VLS_base: import("vue").DefineComponent<import("vue").ExtractPropTypes<{
|
|
7
9
|
for: {
|
package/vue/UiTooltip.vue
CHANGED
|
@@ -312,7 +312,10 @@ useComponentHost(() => import('../components/ui-tooltip/ui-tooltip.js'), {
|
|
|
312
312
|
:data-trigger="reflectedProp('trigger', 'trigger', checkedProps.trigger, undefined, false)"
|
|
313
313
|
:data-ui-tooltip-state="hostState || undefined"
|
|
314
314
|
ref="root"
|
|
315
|
-
><div class="surface"
|
|
315
|
+
><div class="surface">
|
|
316
|
+
<slot />
|
|
317
|
+
<span class="shortcut"><slot name="shortcut" /></span>
|
|
318
|
+
</div></span>
|
|
316
319
|
</template>
|
|
317
320
|
|
|
318
321
|
<style scoped>
|
|
@@ -410,6 +413,29 @@ useComponentHost(() => import('../components/ui-tooltip/ui-tooltip.js'), {
|
|
|
410
413
|
);
|
|
411
414
|
}
|
|
412
415
|
|
|
416
|
+
/* A keyboard shortcut follows the label after a thin divider, smaller and quieter, as menus show
|
|
417
|
+
it. The label stays first in the description, so a screen reader hears the name, then the keys. */
|
|
418
|
+
.shortcut {
|
|
419
|
+
display: inline-flex;
|
|
420
|
+
align-items: center;
|
|
421
|
+
margin-inline-start: var(--ui-space-2);
|
|
422
|
+
padding-inline-start: var(--ui-space-2);
|
|
423
|
+
border-inline-start: 1px solid color-mix(in oklab, currentColor 28%, transparent);
|
|
424
|
+
color: color-mix(in oklab, currentColor 72%, transparent);
|
|
425
|
+
font-size: var(--ui-font-size-xs);
|
|
426
|
+
font-weight: var(--ui-font-normal);
|
|
427
|
+
white-space: nowrap;
|
|
428
|
+
vertical-align: baseline;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
.shortcut:empty {
|
|
432
|
+
display: none;
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
.shortcut kbd {
|
|
436
|
+
font: inherit;
|
|
437
|
+
}
|
|
438
|
+
|
|
413
439
|
[data-component~="ui-tooltip"][data-ui-tooltip-state~="inverse"] .surface {
|
|
414
440
|
--_tooltip-line: var(--_ui-tooltip-inverse-surface, var(--ui-text-primary));
|
|
415
441
|
background: var(--_ui-tooltip-inverse-surface, var(--ui-text-primary));
|
package/vue/chunks/UiTooltip.js
CHANGED
|
@@ -15,6 +15,7 @@ var _hoisted_1 = [
|
|
|
15
15
|
"data-ui-tooltip-state"
|
|
16
16
|
];
|
|
17
17
|
var _hoisted_2 = { class: "surface" };
|
|
18
|
+
var _hoisted_3 = { class: "shortcut" };
|
|
18
19
|
//#endregion
|
|
19
20
|
//#region .build/vue/UiTooltip.vue
|
|
20
21
|
var UiTooltip_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PURE__ */ defineComponent({
|
|
@@ -253,12 +254,12 @@ var UiTooltip_default = /*#__PURE__*/ _plugin_vue_export_helper_default(/* @__PU
|
|
|
253
254
|
"data-ui-tooltip-state": hostState.value || void 0,
|
|
254
255
|
ref_key: "root",
|
|
255
256
|
ref: root
|
|
256
|
-
}), [createElementVNode("div", _hoisted_2, [renderSlot(_ctx.$slots, "default", {}, void 0, true)])], 16, _hoisted_1)), [[unref(vPropValidity), {
|
|
257
|
+
}), [createElementVNode("div", _hoisted_2, [renderSlot(_ctx.$slots, "default", {}, void 0, true), createElementVNode("span", _hoisted_3, [renderSlot(_ctx.$slots, "shortcut", {}, void 0, true)])])], 16, _hoisted_1)), [[unref(vPropValidity), {
|
|
257
258
|
contract: propValidityContract,
|
|
258
259
|
values: { ...checkedProps.value }
|
|
259
260
|
}]]);
|
|
260
261
|
};
|
|
261
262
|
}
|
|
262
|
-
}), [["__scopeId", "data-v-
|
|
263
|
+
}), [["__scopeId", "data-v-3762dc6a"]]);
|
|
263
264
|
//#endregion
|
|
264
265
|
export { UiTooltip_default as t };
|
package/vue/components.css
CHANGED
|
@@ -1484,7 +1484,7 @@ input[data-v-101ef53e]:focus-visible {
|
|
|
1484
1484
|
syntax: "*";
|
|
1485
1485
|
inherits: false;
|
|
1486
1486
|
}
|
|
1487
|
-
[data-component~="ui-tooltip"][data-v-
|
|
1487
|
+
[data-component~="ui-tooltip"][data-v-3762dc6a] {
|
|
1488
1488
|
/* Hooks do not inherit, so the parts below read them from the root. */
|
|
1489
1489
|
--_ui-tooltip-border: var(--ui-tooltip-border);
|
|
1490
1490
|
--_ui-tooltip-max-inline-size: var(--ui-tooltip-max-inline-size);
|
|
@@ -1516,7 +1516,7 @@ input[data-v-101ef53e]:focus-visible {
|
|
|
1516
1516
|
display var(--ui-motion-fast) allow-discrete,
|
|
1517
1517
|
overlay var(--ui-motion-fast) allow-discrete;
|
|
1518
1518
|
}
|
|
1519
|
-
.surface[data-v-
|
|
1519
|
+
.surface[data-v-3762dc6a] {
|
|
1520
1520
|
--_tooltip-line: var(--_ui-tooltip-border, var(--ui-overlay-border, var(--ui-border-strong)));
|
|
1521
1521
|
position: relative;
|
|
1522
1522
|
box-sizing: border-box;
|
|
@@ -1534,7 +1534,28 @@ input[data-v-101ef53e]:focus-visible {
|
|
|
1534
1534
|
var(--ui-overlay-shadow, var(--ui-elevation-tooltip, var(--ui-shadow-md)))
|
|
1535
1535
|
);
|
|
1536
1536
|
}
|
|
1537
|
-
|
|
1537
|
+
|
|
1538
|
+
/* A keyboard shortcut follows the label after a thin divider, smaller and quieter, as menus show
|
|
1539
|
+
it. The label stays first in the description, so a screen reader hears the name, then the keys. */
|
|
1540
|
+
.shortcut[data-v-3762dc6a] {
|
|
1541
|
+
display: inline-flex;
|
|
1542
|
+
align-items: center;
|
|
1543
|
+
margin-inline-start: var(--ui-space-2);
|
|
1544
|
+
padding-inline-start: var(--ui-space-2);
|
|
1545
|
+
border-inline-start: 1px solid color-mix(in oklab, currentColor 28%, transparent);
|
|
1546
|
+
color: color-mix(in oklab, currentColor 72%, transparent);
|
|
1547
|
+
font-size: var(--ui-font-size-xs);
|
|
1548
|
+
font-weight: var(--ui-font-normal);
|
|
1549
|
+
white-space: nowrap;
|
|
1550
|
+
vertical-align: baseline;
|
|
1551
|
+
}
|
|
1552
|
+
.shortcut[data-v-3762dc6a]:empty {
|
|
1553
|
+
display: none;
|
|
1554
|
+
}
|
|
1555
|
+
.shortcut kbd[data-v-3762dc6a] {
|
|
1556
|
+
font: inherit;
|
|
1557
|
+
}
|
|
1558
|
+
[data-component~="ui-tooltip"][data-ui-tooltip-state~="inverse"] .surface[data-v-3762dc6a] {
|
|
1538
1559
|
--_tooltip-line: var(--_ui-tooltip-inverse-surface, var(--ui-text-primary));
|
|
1539
1560
|
background: var(--_ui-tooltip-inverse-surface, var(--ui-text-primary));
|
|
1540
1561
|
color: var(--_ui-tooltip-inverse-text, var(--ui-surface-default));
|
|
@@ -1542,7 +1563,7 @@ input[data-v-101ef53e]:focus-visible {
|
|
|
1542
1563
|
|
|
1543
1564
|
/* A rotated square shares the surface fill and draws the two outward border edges. Its centre sits on
|
|
1544
1565
|
* the surface border line, so the fill covers that stretch of border and the outline runs unbroken. */
|
|
1545
|
-
.surface[data-v-
|
|
1566
|
+
.surface[data-v-3762dc6a]::after {
|
|
1546
1567
|
content: "";
|
|
1547
1568
|
position: absolute;
|
|
1548
1569
|
z-index: 1;
|
|
@@ -1558,7 +1579,7 @@ input[data-v-101ef53e]:focus-visible {
|
|
|
1558
1579
|
border-end-end-radius: 1px;
|
|
1559
1580
|
transform: rotate(45deg) scaleX(1.25) scaleY(0.85);
|
|
1560
1581
|
}
|
|
1561
|
-
[data-component~="ui-tooltip"][data-ui-actual-placement="bottom"] .surface[data-v-
|
|
1582
|
+
[data-component~="ui-tooltip"][data-ui-actual-placement="bottom"] .surface[data-v-3762dc6a]::after {
|
|
1562
1583
|
inset-block-start: calc(var(--_ui-tooltip-arrow-size, 0.625rem) / -2 - 0.5px);
|
|
1563
1584
|
inset-block-end: auto;
|
|
1564
1585
|
border-inline-end-width: 0;
|
|
@@ -1568,59 +1589,59 @@ input[data-v-101ef53e]:focus-visible {
|
|
|
1568
1589
|
border-end-end-radius: 0;
|
|
1569
1590
|
border-start-start-radius: 1px;
|
|
1570
1591
|
}
|
|
1571
|
-
[data-component~="ui-tooltip"][data-ui-actual-align="center"] .surface[data-v-
|
|
1592
|
+
[data-component~="ui-tooltip"][data-ui-actual-align="center"] .surface[data-v-3762dc6a]::after {
|
|
1572
1593
|
inset-inline-start: calc(50% - var(--_ui-tooltip-arrow-size, 0.625rem) / 2);
|
|
1573
1594
|
}
|
|
1574
|
-
[data-component~="ui-tooltip"][data-ui-actual-align="end"] .surface[data-v-
|
|
1595
|
+
[data-component~="ui-tooltip"][data-ui-actual-align="end"] .surface[data-v-3762dc6a]::after {
|
|
1575
1596
|
inset-inline-start: auto;
|
|
1576
1597
|
inset-inline-end: var(--ui-space-3);
|
|
1577
1598
|
}
|
|
1578
|
-
[data-component~="ui-tooltip"][data-ui-actual-placement="left"] .surface[data-v-
|
|
1579
|
-
[data-component~="ui-tooltip"][data-ui-actual-placement="right"] .surface[data-v-
|
|
1599
|
+
[data-component~="ui-tooltip"][data-ui-actual-placement="left"] .surface[data-v-3762dc6a]::after,
|
|
1600
|
+
[data-component~="ui-tooltip"][data-ui-actual-placement="right"] .surface[data-v-3762dc6a]::after {
|
|
1580
1601
|
inset-block-start: calc(50% - var(--_ui-tooltip-arrow-size, 0.625rem) / 2);
|
|
1581
1602
|
inset-block-end: auto;
|
|
1582
1603
|
border: 0 solid var(--_tooltip-line);
|
|
1583
1604
|
}
|
|
1584
|
-
[data-component~="ui-tooltip"][data-ui-actual-placement="left"] .surface[data-v-
|
|
1605
|
+
[data-component~="ui-tooltip"][data-ui-actual-placement="left"] .surface[data-v-3762dc6a]::after {
|
|
1585
1606
|
inset-inline-start: auto;
|
|
1586
1607
|
inset-inline-end: calc(var(--_ui-tooltip-arrow-size, 0.625rem) / -2 - 0.5px);
|
|
1587
1608
|
border-inline-end-width: 1px;
|
|
1588
1609
|
border-block-start-width: 1px;
|
|
1589
1610
|
}
|
|
1590
|
-
[data-component~="ui-tooltip"][data-ui-actual-placement="right"] .surface[data-v-
|
|
1611
|
+
[data-component~="ui-tooltip"][data-ui-actual-placement="right"] .surface[data-v-3762dc6a]::after {
|
|
1591
1612
|
inset-inline-start: calc(var(--_ui-tooltip-arrow-size, 0.625rem) / -2 - 0.5px);
|
|
1592
1613
|
inset-inline-end: auto;
|
|
1593
1614
|
border-inline-start-width: 1px;
|
|
1594
1615
|
border-block-end-width: 1px;
|
|
1595
1616
|
}
|
|
1596
1617
|
[data-component~="ui-tooltip"][data-ui-actual-placement="left"][data-ui-actual-align="start"]
|
|
1597
|
-
.surface[data-v-
|
|
1618
|
+
.surface[data-v-3762dc6a]::after,
|
|
1598
1619
|
[data-component~="ui-tooltip"][data-ui-actual-placement="right"][data-ui-actual-align="start"]
|
|
1599
|
-
.surface[data-v-
|
|
1620
|
+
.surface[data-v-3762dc6a]::after {
|
|
1600
1621
|
inset-block-start: var(--ui-space-3);
|
|
1601
1622
|
}
|
|
1602
1623
|
[data-component~="ui-tooltip"][data-ui-actual-placement="left"][data-ui-actual-align="end"]
|
|
1603
|
-
.surface[data-v-
|
|
1624
|
+
.surface[data-v-3762dc6a]::after,
|
|
1604
1625
|
[data-component~="ui-tooltip"][data-ui-actual-placement="right"][data-ui-actual-align="end"]
|
|
1605
|
-
.surface[data-v-
|
|
1626
|
+
.surface[data-v-3762dc6a]::after {
|
|
1606
1627
|
inset-block-start: auto;
|
|
1607
1628
|
inset-block-end: var(--ui-space-3);
|
|
1608
1629
|
}
|
|
1609
|
-
[data-component~="ui-tooltip"][data-v-
|
|
1630
|
+
[data-component~="ui-tooltip"][data-v-3762dc6a]:popover-open {
|
|
1610
1631
|
opacity: 1;
|
|
1611
1632
|
transform: translateY(0);
|
|
1612
1633
|
}
|
|
1613
1634
|
@starting-style {
|
|
1614
|
-
[data-component~="ui-tooltip"][data-v-
|
|
1635
|
+
[data-component~="ui-tooltip"][data-v-3762dc6a]:popover-open {
|
|
1615
1636
|
opacity: 0;
|
|
1616
1637
|
transform: translateY(4px);
|
|
1617
1638
|
}
|
|
1618
1639
|
}
|
|
1619
|
-
[data-component~="ui-tooltip"][hidden][data-v-
|
|
1640
|
+
[data-component~="ui-tooltip"][hidden][data-v-3762dc6a] {
|
|
1620
1641
|
display: none;
|
|
1621
1642
|
}
|
|
1622
1643
|
@media (prefers-reduced-motion: reduce) {
|
|
1623
|
-
[data-component~="ui-tooltip"][data-v-
|
|
1644
|
+
[data-component~="ui-tooltip"][data-v-3762dc6a] {
|
|
1624
1645
|
transition: none;
|
|
1625
1646
|
}
|
|
1626
1647
|
}
|
package/vue/editor/index.js
CHANGED
|
@@ -403,6 +403,23 @@ var autoCodeLanguageNames = [
|
|
|
403
403
|
];
|
|
404
404
|
//#endregion
|
|
405
405
|
//#region src/vue/editor/LoomaEditor.ts
|
|
406
|
+
/**
|
|
407
|
+
* Shows a key binding in ProseMirror notation ("Mod-Shift-8") the way the reader's platform writes
|
|
408
|
+
* it: modifier symbols in Apple's order on Apple devices (⇧⌘8), and Ctrl+Shift+8 elsewhere.
|
|
409
|
+
*/
|
|
410
|
+
function formatEditorShortcut(keys, apple) {
|
|
411
|
+
const parts = keys.split("-");
|
|
412
|
+
const key = (parts.pop() ?? "").toUpperCase();
|
|
413
|
+
const has = (name) => parts.includes(name);
|
|
414
|
+
if (apple) return `${has("Ctrl") ? "⌃" : ""}${has("Alt") ? "⌥" : ""}${has("Shift") ? "⇧" : ""}${has("Mod") ? "⌘" : ""}${key}`;
|
|
415
|
+
return [
|
|
416
|
+
has("Mod") || has("Ctrl") ? "Ctrl" : "",
|
|
417
|
+
has("Alt") ? "Alt" : "",
|
|
418
|
+
has("Shift") ? "Shift" : "",
|
|
419
|
+
key
|
|
420
|
+
].filter(Boolean).join("+");
|
|
421
|
+
}
|
|
422
|
+
var isApplePlatform = () => typeof navigator !== "undefined" && /Mac|iPhone|iPad|iPod/.test(navigator.userAgentData?.platform || navigator.platform || navigator.userAgent);
|
|
406
423
|
var EMPTY_DOCUMENT = {
|
|
407
424
|
type: "doc",
|
|
408
425
|
content: []
|
|
@@ -606,16 +623,18 @@ var LoomaEditor = defineComponent({
|
|
|
606
623
|
const toolbarScope = `looma-editor-tool-${useId().replace(/[^a-zA-Z0-9_-]/g, "")}`;
|
|
607
624
|
const tooltipFor = ref("");
|
|
608
625
|
const tooltipLabel = ref("");
|
|
626
|
+
const tooltipShortcut = ref("");
|
|
609
627
|
const tooltipOpen = ref(false);
|
|
610
628
|
let tooltipTimer = 0;
|
|
611
629
|
const clearTooltipTimer = () => {
|
|
612
630
|
if (tooltipTimer) window.clearTimeout(tooltipTimer);
|
|
613
631
|
tooltipTimer = 0;
|
|
614
632
|
};
|
|
615
|
-
const showTool = (id, label, immediate) => {
|
|
633
|
+
const showTool = (id, label, immediate, shortcut = "") => {
|
|
616
634
|
clearTooltipTimer();
|
|
617
635
|
tooltipFor.value = id;
|
|
618
636
|
tooltipLabel.value = label;
|
|
637
|
+
tooltipShortcut.value = shortcut ? formatEditorShortcut(shortcut, isApplePlatform()) : "";
|
|
619
638
|
if (immediate || tooltipOpen.value) {
|
|
620
639
|
tooltipOpen.value = true;
|
|
621
640
|
return;
|
|
@@ -1507,7 +1526,7 @@ var LoomaEditor = defineComponent({
|
|
|
1507
1526
|
const onTableOverlayMouseDown = (event) => {
|
|
1508
1527
|
if (event.target instanceof Element ? event.target.closest("button[data-action]") : null) event.preventDefault();
|
|
1509
1528
|
};
|
|
1510
|
-
const commandButton = (label, icon, active, disabled, run) => {
|
|
1529
|
+
const commandButton = (label, icon, active, disabled, run, shortcut = "") => {
|
|
1511
1530
|
const syncNativeDisabled = (vnode) => {
|
|
1512
1531
|
if (!(vnode.el instanceof Element)) return;
|
|
1513
1532
|
const button = vnode.el instanceof HTMLButtonElement ? vnode.el : vnode.el.querySelector("button");
|
|
@@ -1519,9 +1538,9 @@ var LoomaEditor = defineComponent({
|
|
|
1519
1538
|
class: "looma-editor__toolbar-button",
|
|
1520
1539
|
label,
|
|
1521
1540
|
size: "sm",
|
|
1522
|
-
onPointerenter: () => showTool(id, label, false),
|
|
1541
|
+
onPointerenter: () => showTool(id, label, false, shortcut),
|
|
1523
1542
|
onPointerleave: hideTool,
|
|
1524
|
-
onFocusin: () => showTool(id, label, true),
|
|
1543
|
+
onFocusin: () => showTool(id, label, true, shortcut),
|
|
1525
1544
|
onFocusout: hideTool,
|
|
1526
1545
|
variant: "ghost",
|
|
1527
1546
|
disabled,
|
|
@@ -1534,12 +1553,12 @@ var LoomaEditor = defineComponent({
|
|
|
1534
1553
|
};
|
|
1535
1554
|
const renderToolbar = (instance, floating = true, textOnly = false) => {
|
|
1536
1555
|
const textButtons = [
|
|
1537
|
-
commandButton("Bold", "bold", instance.isActive("bold"), !instance.can().toggleBold(), () => instance.chain().focus().toggleBold().run()),
|
|
1538
|
-
commandButton("Italic", "italic", instance.isActive("italic"), !instance.can().toggleItalic(), () => instance.chain().focus().toggleItalic().run()),
|
|
1539
|
-
commandButton("Underline", "underline", instance.isActive("underline"), !instance.can().toggleUnderline(), () => instance.chain().focus().toggleUnderline().run()),
|
|
1540
|
-
commandButton("Strike", "strikethrough", instance.isActive("strike"), !instance.can().toggleStrike(), () => instance.chain().focus().toggleStrike().run()),
|
|
1541
|
-
...authorHighlight ? [commandButton("Highlight", "highlighter", instance.isActive("highlight"), !instance.can().toggleHighlight(), () => instance.chain().focus().toggleHighlight().run())] : [],
|
|
1542
|
-
commandButton("Inline code", "code-xml", instance.isActive("code"), !instance.can().toggleCode(), () => instance.chain().focus().toggleCode().run())
|
|
1556
|
+
commandButton("Bold", "bold", instance.isActive("bold"), !instance.can().toggleBold(), () => instance.chain().focus().toggleBold().run(), "Mod-b"),
|
|
1557
|
+
commandButton("Italic", "italic", instance.isActive("italic"), !instance.can().toggleItalic(), () => instance.chain().focus().toggleItalic().run(), "Mod-i"),
|
|
1558
|
+
commandButton("Underline", "underline", instance.isActive("underline"), !instance.can().toggleUnderline(), () => instance.chain().focus().toggleUnderline().run(), "Mod-u"),
|
|
1559
|
+
commandButton("Strike", "strikethrough", instance.isActive("strike"), !instance.can().toggleStrike(), () => instance.chain().focus().toggleStrike().run(), "Mod-Shift-s"),
|
|
1560
|
+
...authorHighlight ? [commandButton("Highlight", "highlighter", instance.isActive("highlight"), !instance.can().toggleHighlight(), () => instance.chain().focus().toggleHighlight().run(), "Mod-Shift-h")] : [],
|
|
1561
|
+
commandButton("Inline code", "code-xml", instance.isActive("code"), !instance.can().toggleCode(), () => instance.chain().focus().toggleCode().run(), "Mod-e")
|
|
1543
1562
|
];
|
|
1544
1563
|
const buttons = textOnly ? textButtons : [
|
|
1545
1564
|
...textButtons,
|
|
@@ -1568,13 +1587,13 @@ var LoomaEditor = defineComponent({
|
|
|
1568
1587
|
class: "divider",
|
|
1569
1588
|
"aria-hidden": "true"
|
|
1570
1589
|
}),
|
|
1571
|
-
commandButton("Heading 1", "heading-1", instance.isActive("heading", { level: 1 }), false, () => instance.chain().focus().toggleHeading({ level: 1 }).run()),
|
|
1572
|
-
commandButton("Heading 2", "heading-2", instance.isActive("heading", { level: 2 }), false, () => instance.chain().focus().toggleHeading({ level: 2 }).run()),
|
|
1573
|
-
commandButton("Heading 3", "heading-3", instance.isActive("heading", { level: 3 }), false, () => instance.chain().focus().toggleHeading({ level: 3 }).run()),
|
|
1574
|
-
commandButton("Bullet list", "list", instance.isActive("bulletList"), false, () => instance.chain().focus().toggleBulletList().run()),
|
|
1575
|
-
commandButton("Numbered list", "list-ordered", instance.isActive("orderedList"), false, () => instance.chain().focus().toggleOrderedList().run()),
|
|
1576
|
-
commandButton("Blockquote", "quote", instance.isActive("blockquote"), !instance.can().toggleBlockquote(), () => instance.chain().focus().toggleBlockquote().run()),
|
|
1577
|
-
commandButton("Code block", "braces", instance.isActive("codeBlock"), !instance.can().toggleCodeBlock(), () => instance.chain().focus().toggleCodeBlock().run()),
|
|
1590
|
+
commandButton("Heading 1", "heading-1", instance.isActive("heading", { level: 1 }), false, () => instance.chain().focus().toggleHeading({ level: 1 }).run(), "Mod-Alt-1"),
|
|
1591
|
+
commandButton("Heading 2", "heading-2", instance.isActive("heading", { level: 2 }), false, () => instance.chain().focus().toggleHeading({ level: 2 }).run(), "Mod-Alt-2"),
|
|
1592
|
+
commandButton("Heading 3", "heading-3", instance.isActive("heading", { level: 3 }), false, () => instance.chain().focus().toggleHeading({ level: 3 }).run(), "Mod-Alt-3"),
|
|
1593
|
+
commandButton("Bullet list", "list", instance.isActive("bulletList"), false, () => instance.chain().focus().toggleBulletList().run(), "Mod-Shift-8"),
|
|
1594
|
+
commandButton("Numbered list", "list-ordered", instance.isActive("orderedList"), false, () => instance.chain().focus().toggleOrderedList().run(), "Mod-Shift-7"),
|
|
1595
|
+
commandButton("Blockquote", "quote", instance.isActive("blockquote"), !instance.can().toggleBlockquote(), () => instance.chain().focus().toggleBlockquote().run(), "Mod-Shift-b"),
|
|
1596
|
+
commandButton("Code block", "braces", instance.isActive("codeBlock"), !instance.can().toggleCodeBlock(), () => instance.chain().focus().toggleCodeBlock().run(), "Mod-Alt-c"),
|
|
1578
1597
|
h(IconButton, {
|
|
1579
1598
|
id: blockActionAnchorId,
|
|
1580
1599
|
class: "looma-editor__toolbar-button",
|
|
@@ -1607,8 +1626,8 @@ var LoomaEditor = defineComponent({
|
|
|
1607
1626
|
class: "divider",
|
|
1608
1627
|
"aria-hidden": "true"
|
|
1609
1628
|
}),
|
|
1610
|
-
commandButton("Undo", "undo", false, !instance.can().undo(), () => instance.chain().focus().undo().run()),
|
|
1611
|
-
commandButton("Redo", "redo", false, !instance.can().redo(), () => instance.chain().focus().redo().run())
|
|
1629
|
+
commandButton("Undo", "undo", false, !instance.can().undo(), () => instance.chain().focus().undo().run(), "Mod-z"),
|
|
1630
|
+
commandButton("Redo", "redo", false, !instance.can().redo(), () => instance.chain().focus().redo().run(), isApplePlatform() ? "Mod-Shift-z" : "Mod-y")
|
|
1612
1631
|
];
|
|
1613
1632
|
return h(EditorToolbar, { floating }, () => [...buttons, h(Tooltip, {
|
|
1614
1633
|
class: "looma-editor__toolbar-tip",
|
|
@@ -1616,7 +1635,10 @@ var LoomaEditor = defineComponent({
|
|
|
1616
1635
|
open: tooltipOpen.value,
|
|
1617
1636
|
placement: floating ? "top" : "bottom",
|
|
1618
1637
|
trigger: "focus"
|
|
1619
|
-
},
|
|
1638
|
+
}, {
|
|
1639
|
+
default: () => tooltipLabel.value,
|
|
1640
|
+
shortcut: () => tooltipShortcut.value ? h("kbd", tooltipShortcut.value) : null
|
|
1641
|
+
})]);
|
|
1620
1642
|
};
|
|
1621
1643
|
const focus = (position = "start") => {
|
|
1622
1644
|
editor.value?.commands.focus(position);
|