@threadlabs/looma 0.38.0 → 0.39.1
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/EXPRESSIVE-MARKDOWN.md +2 -0
- package/README.md +1 -1
- package/components/ui-skeleton/ui-skeleton.html +36 -7
- package/components/ui-skeleton/ui-skeleton.js +46 -0
- package/dist/index.js +13 -12
- package/docs/README.md +3 -3
- package/docs/catalog.json +9 -9
- package/docs/cli.mjs +1 -1
- package/docs/commands.mjs +2 -2
- package/docs/index.d.ts +3 -3
- package/docs/local-server.mjs +1 -1
- package/docs/site.mjs +6 -6
- package/editor/expressmark.js +12 -4
- package/package.json +6 -6
- package/styles/ui-skeleton.css +30 -5
- package/vanilla/UiSkeleton.js +5 -3
- package/vue/UiSkeleton.vue +71 -10
- package/vue/chunks/UiSkeleton.js +41 -9
- package/vue/components.css +30 -4
package/EXPRESSIVE-MARKDOWN.md
CHANGED
|
@@ -25,6 +25,8 @@ const markdown = stringify(ast);
|
|
|
25
25
|
const restoredEditorJson = expressmarkToEditorDocument(parse(markdown));
|
|
26
26
|
```
|
|
27
27
|
|
|
28
|
+
Editor Markdown import and export explicitly select Expressmark’s `compatible` syntax (CommonMark/GFM with expressive extensions), preserving the existing interchange format as Expressmark’s defaults evolve. Pass `syntax` in conversion options when selecting another supported reading; content outside the editor schema still raises a conversion error.
|
|
29
|
+
|
|
28
30
|
The editor continues to save Tiptap JSON. Expressive Markdown is an interchange
|
|
29
31
|
format; it does not replace your saved document, history or application metadata.
|
|
30
32
|
See the [proposal and syntax](https://nextwebwg.org/expressive-markdown/) and
|
package/README.md
CHANGED
|
@@ -67,7 +67,7 @@ The package includes the documentation generator and theme customizer used by Lo
|
|
|
67
67
|
Install the optional documentation tools, then initialize your project:
|
|
68
68
|
|
|
69
69
|
```sh
|
|
70
|
-
pnpm add -D markupress @
|
|
70
|
+
pnpm add -D markupress @threadlabs/markupkit@0.2.0 vite
|
|
71
71
|
pnpm exec looma-docs init
|
|
72
72
|
pnpm exec looma-docs dev
|
|
73
73
|
```
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
<template component="ui-skeleton">
|
|
1
|
+
<template component="ui-skeleton" module="./ui-skeleton.js">
|
|
2
2
|
<defs>
|
|
3
3
|
<prop name="shape" type="keyword" values="text, circle, rectangle" default="text"
|
|
4
4
|
>The content's silhouette. text reserves one inherited line box with a shorter bar inside it; circle matches a medium Avatar; rectangle reserves a media
|
|
@@ -8,8 +8,12 @@
|
|
|
8
8
|
Avatar's outer size for circles.</prop>
|
|
9
9
|
<prop name="height" type="string" default=""
|
|
10
10
|
>Block size as a CSS length. Empty reserves one line for text, a square for circles, or 8rem for rectangles. Set only width to keep a circle square.</prop>
|
|
11
|
-
<prop
|
|
12
|
-
|
|
11
|
+
<prop
|
|
12
|
+
name="animated"
|
|
13
|
+
type="boolean"
|
|
14
|
+
default="true"
|
|
15
|
+
default-true-reason="A travelling highlight identifies pending content by default; reduced-motion preferences always keep it static."
|
|
16
|
+
>Moves a subtle highlight from left to right. On by default; pass false to keep it static. Reduced-motion preferences always disable the shimmer.</prop>
|
|
13
17
|
</defs>
|
|
14
18
|
<span aria-hidden="true" style:--ui-skeleton-width="$width" style:--ui-skeleton-height="$height"></span>
|
|
15
19
|
<style>
|
|
@@ -22,8 +26,20 @@
|
|
|
22
26
|
syntax: "*";
|
|
23
27
|
inherits: false;
|
|
24
28
|
}
|
|
29
|
+
@property --_ui-skeleton-viewport-x {
|
|
30
|
+
syntax: "<length>";
|
|
31
|
+
inherits: false;
|
|
32
|
+
initial-value: 0px;
|
|
33
|
+
}
|
|
34
|
+
@property --_ui-skeleton-viewport-scale {
|
|
35
|
+
syntax: "<number>";
|
|
36
|
+
inherits: false;
|
|
37
|
+
initial-value: 1;
|
|
38
|
+
}
|
|
25
39
|
|
|
26
40
|
:host {
|
|
41
|
+
--_ui-skeleton-paint-x: var(--_ui-skeleton-viewport-x);
|
|
42
|
+
--_ui-skeleton-paint-scale: var(--_ui-skeleton-viewport-scale);
|
|
27
43
|
display: block !important;
|
|
28
44
|
position: relative;
|
|
29
45
|
box-sizing: border-box !important;
|
|
@@ -65,23 +81,36 @@
|
|
|
65
81
|
}
|
|
66
82
|
|
|
67
83
|
:host([animated])::before {
|
|
68
|
-
|
|
84
|
+
background-image: linear-gradient(
|
|
85
|
+
90deg,
|
|
86
|
+
transparent,
|
|
87
|
+
light-dark(rgb(255 255 255 / 0.6), rgb(255 255 255 / 0.14)) 50%,
|
|
88
|
+
transparent
|
|
89
|
+
);
|
|
90
|
+
background-size: calc(100vw / var(--_ui-skeleton-paint-scale)) 100%;
|
|
91
|
+
background-position: calc(0vw - var(--_ui-skeleton-paint-x)) 0;
|
|
92
|
+
background-repeat: repeat-x;
|
|
93
|
+
animation: ui-skeleton-shimmer 3s linear infinite;
|
|
69
94
|
}
|
|
70
|
-
@keyframes ui-skeleton-
|
|
71
|
-
|
|
72
|
-
|
|
95
|
+
@keyframes ui-skeleton-shimmer {
|
|
96
|
+
to {
|
|
97
|
+
background-position: calc(100vw / var(--_ui-skeleton-paint-scale) - var(--_ui-skeleton-paint-x)) 0;
|
|
73
98
|
}
|
|
74
99
|
}
|
|
75
100
|
@media (prefers-reduced-motion: reduce) {
|
|
76
101
|
:host([animated])::before {
|
|
77
102
|
animation: none;
|
|
103
|
+
background-image: none;
|
|
78
104
|
}
|
|
79
105
|
}
|
|
80
106
|
@media (forced-colors: active) {
|
|
81
107
|
:host::before {
|
|
82
108
|
background: CanvasText;
|
|
83
109
|
opacity: 0.2;
|
|
110
|
+
}
|
|
111
|
+
:host([animated])::before {
|
|
84
112
|
animation: none;
|
|
113
|
+
background-image: none;
|
|
85
114
|
}
|
|
86
115
|
}
|
|
87
116
|
:host[hidden] {
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keep one viewport gradient aligned through mounting, scrolling and transformed surfaces.
|
|
3
|
+
* @lifecycle CSS owns motion preferences; geometry tracking stops with the animation or disconnect.
|
|
4
|
+
*/
|
|
5
|
+
export function connect(host) {
|
|
6
|
+
const element = host.element;
|
|
7
|
+
const view = element.ownerDocument.defaultView;
|
|
8
|
+
let motion;
|
|
9
|
+
let frame = 0;
|
|
10
|
+
let previousPosition = "";
|
|
11
|
+
let previousScale = "";
|
|
12
|
+
const trackPosition = () => {
|
|
13
|
+
frame = 0;
|
|
14
|
+
if (motion?.playState !== "running") return;
|
|
15
|
+
const bounds = element.getBoundingClientRect();
|
|
16
|
+
const width = parseFloat(view.getComputedStyle(element).width);
|
|
17
|
+
const scale = bounds.width > 0 && width > 0 ? bounds.width / width : 1;
|
|
18
|
+
const position = `${bounds.left / scale}px`;
|
|
19
|
+
const scaleValue = String(scale);
|
|
20
|
+
if (position !== previousPosition) {
|
|
21
|
+
element.style.setProperty("--_ui-skeleton-viewport-x", position);
|
|
22
|
+
previousPosition = position;
|
|
23
|
+
}
|
|
24
|
+
if (scaleValue !== previousScale) {
|
|
25
|
+
element.style.setProperty("--_ui-skeleton-viewport-scale", scaleValue);
|
|
26
|
+
previousScale = scaleValue;
|
|
27
|
+
}
|
|
28
|
+
frame = view.requestAnimationFrame(trackPosition);
|
|
29
|
+
};
|
|
30
|
+
const synchronize = () => {
|
|
31
|
+
const names = view.getComputedStyle(element, "::before").animationName.split(",").map(name => name.trim());
|
|
32
|
+
for (const animation of element.getAnimations({ subtree: true })) {
|
|
33
|
+
if (names.includes(animation.animationName)) {
|
|
34
|
+
motion = animation;
|
|
35
|
+
motion.startTime = 0;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (!frame) trackPosition();
|
|
39
|
+
};
|
|
40
|
+
element.addEventListener("animationstart", synchronize);
|
|
41
|
+
synchronize();
|
|
42
|
+
return () => {
|
|
43
|
+
element.removeEventListener("animationstart", synchronize);
|
|
44
|
+
view.cancelAnimationFrame(frame);
|
|
45
|
+
};
|
|
46
|
+
}
|