@dumiflex/wp-kit 0.6.0 → 0.7.0
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/CHANGELOG.md +15 -0
- package/package.json +1 -1
- package/src/BundlePreview.vue +254 -0
- package/src/CombinePreview.vue +150 -0
- package/src/ConstraintMatrixPreview.vue +6 -22
- package/src/ConstraintPreview.vue +259 -0
- package/src/DerivationCondition.vue +68 -0
- package/src/DerivationPreview.vue +345 -0
- package/src/FixedValuesPreview.vue +184 -0
- package/src/IconPicker.vue +31 -102
- package/src/IconPickerPanel.vue +132 -0
- package/src/LoadingMark.vue +6 -61
- package/src/PayloadPreview.vue +154 -0
- package/src/PostDetailSkeleton.vue +65 -0
- package/src/PostGridSkeleton.vue +61 -0
- package/src/PreviewGroup.vue +75 -0
- package/src/ProfileSkeleton.vue +73 -0
- package/src/RichText.vue +61 -0
- package/src/SelectionBar.vue +90 -0
- package/src/SettingGroup.vue +57 -0
- package/src/SettingRow.vue +127 -0
- package/src/WildcardPreview.vue +607 -0
- package/src/WorkingLine.vue +38 -124
- package/src/canvas-motion.ts +251 -0
- package/src/kind-colour.ts +24 -1
- package/src/linkify.ts +142 -0
- package/src/loading-mark-motion.ts +12 -155
- package/src/matrix-axis.ts +28 -0
- package/src/pi-icons.ts +51 -0
- package/src/preview-readers.ts +401 -0
- package/src/preview.css +194 -0
- package/src/tokens.ts +8 -2
- package/src/working-line-motion.ts +135 -0
|
@@ -1,66 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* LoadingMark's motion, drawn on a canvas.
|
|
3
|
-
*
|
|
4
|
-
* The mark used to move its SVG paths with CSS. A keyframed `transform` /
|
|
5
|
-
* `opacity` goes to the compositor, which blurs the path and snaps it to whole
|
|
6
|
-
* pixels as it starts; animating registered custom properties fixed that in
|
|
7
|
-
* Chromium, but Firefox still lays each frame of an SVG transform on the pixel
|
|
8
|
-
* grid, so the rings stepped and twitched as they slid. A canvas puts every
|
|
9
|
-
* shape at its exact fractional position each frame, sharp and smooth in both.
|
|
10
|
-
*
|
|
11
|
-
* One `requestAnimationFrame` loop draws every mark on the page. Each mark
|
|
12
|
-
* keeps its own clock, so a host can slow or pause the marks inside it with
|
|
13
|
-
* `data-wp-motion-speed` (a number) and `data-wp-motion-paused` on an
|
|
14
|
-
* ancestor, as the kit site's Animations section does.
|
|
2
|
+
* LoadingMark's motion, drawn on a canvas (see `canvas-motion.ts` for why).
|
|
3
|
+
* The same keyframes the mark had in CSS, as eased tracks.
|
|
15
4
|
*/
|
|
16
5
|
import { RING_A, RING_B, STAR_A, STAR_B, STAR_BIG } from "./logo-paths";
|
|
6
|
+
import { EASE_IN_OUT, SMOOTH, begin, fillAround, track, type Stop } from "./canvas-motion";
|
|
17
7
|
|
|
18
8
|
/** One loop of the logo, in ms; the sparkle's swap takes two. */
|
|
19
9
|
export const LOOP_MS = 2400;
|
|
20
|
-
/** Room around the 1024 box for the rings as they slide apart (70 units)
|
|
21
|
-
* and for anti-aliasing at the edge. */
|
|
22
|
-
export const PAD = 82;
|
|
23
|
-
export const BOX = 1024 + 2 * PAD;
|
|
24
|
-
|
|
25
|
-
/** CSS `cubic-bezier(x1, y1, x2, y2)` as a function of progress. */
|
|
26
|
-
export function cubicBezier(x1: number, y1: number, x2: number, y2: number): (x: number) => number {
|
|
27
|
-
return (x) => {
|
|
28
|
-
if (x <= 0) return 0;
|
|
29
|
-
if (x >= 1) return 1;
|
|
30
|
-
let lo = 0;
|
|
31
|
-
let hi = 1;
|
|
32
|
-
let t = x;
|
|
33
|
-
for (let k = 0; k < 30; k++) {
|
|
34
|
-
t = (lo + hi) / 2;
|
|
35
|
-
const cx = 3 * x1 * t * (1 - t) ** 2 + 3 * x2 * t * t * (1 - t) + t ** 3;
|
|
36
|
-
if (cx < x) lo = t;
|
|
37
|
-
else hi = t;
|
|
38
|
-
}
|
|
39
|
-
return 3 * y1 * t * (1 - t) ** 2 + 3 * y2 * t * t * (1 - t) + t ** 3;
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
const SMOOTH = cubicBezier(0.65, 0, 0.35, 1);
|
|
44
|
-
const EASE_IN_OUT = cubicBezier(0.42, 0, 0.58, 1);
|
|
45
|
-
|
|
46
|
-
type Stop = readonly [at: number, values: readonly number[]];
|
|
47
|
-
|
|
48
|
-
/** Value of a keyframe track at progress `p` (0..1), eased per segment the
|
|
49
|
-
* way CSS eases between two keyframes. */
|
|
50
|
-
export function track(stops: readonly Stop[], p: number, ease: (x: number) => number): number[] {
|
|
51
|
-
for (let k = 0; k < stops.length - 1; k++) {
|
|
52
|
-
const a = stops[k];
|
|
53
|
-
const b = stops[k + 1];
|
|
54
|
-
if (!a || !b) break;
|
|
55
|
-
if (p >= a[0] && p <= b[0]) {
|
|
56
|
-
if (b[0] === a[0]) return [...b[1]];
|
|
57
|
-
const e = ease((p - a[0]) / (b[0] - a[0]));
|
|
58
|
-
return a[1].map((v, j) => v + ((b[1][j] ?? v) - v) * e);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
return [...(stops[stops.length - 1]?.[1] ?? [])];
|
|
62
|
-
}
|
|
63
|
-
|
|
64
10
|
/** The rings' slide apart (units of the 1024 box). */
|
|
65
11
|
const SPLIT: readonly Stop[] = [[0, [0]], [0.15, [0]], [0.4, [70]], [0.6, [70]], [0.85, [0]], [1, [0]]];
|
|
66
12
|
/** The big star's dip: [scale, turn in degrees]. */
|
|
@@ -91,12 +37,12 @@ export function poseAt(ms: number): Pose {
|
|
|
91
37
|
}
|
|
92
38
|
|
|
93
39
|
/** Centres of the stars in the 1024 box (from their bounding boxes). */
|
|
94
|
-
const C_BIG = [512, 512] as const;
|
|
95
|
-
const C_A = [360, 664] as const;
|
|
96
|
-
const C_B = [664, 360] as const;
|
|
40
|
+
export const C_BIG = [512, 512] as const;
|
|
41
|
+
export const C_A = [360, 664] as const;
|
|
42
|
+
export const C_B = [664, 360] as const;
|
|
97
43
|
|
|
98
44
|
let paths: Record<"ra" | "rb" | "big" | "a" | "b", Path2D> | null = null;
|
|
99
|
-
function shapes(): Record<"ra" | "rb" | "big" | "a" | "b", Path2D> {
|
|
45
|
+
export function shapes(): Record<"ra" | "rb" | "big" | "a" | "b", Path2D> {
|
|
100
46
|
paths ??= { ra: new Path2D(RING_A), rb: new Path2D(RING_B), big: new Path2D(STAR_BIG), a: new Path2D(STAR_A), b: new Path2D(STAR_B) };
|
|
101
47
|
return paths;
|
|
102
48
|
}
|
|
@@ -109,26 +55,11 @@ export interface Look {
|
|
|
109
55
|
flat: boolean;
|
|
110
56
|
}
|
|
111
57
|
|
|
112
|
-
function around(ctx: CanvasRenderingContext2D, [x, y]: readonly [number, number], scale: number, turn: number, path: Path2D, fill: string, alpha: number): void {
|
|
113
|
-
ctx.save();
|
|
114
|
-
ctx.translate(x, y);
|
|
115
|
-
ctx.rotate((turn * Math.PI) / 180);
|
|
116
|
-
ctx.scale(scale, scale);
|
|
117
|
-
ctx.translate(-x, -y);
|
|
118
|
-
ctx.globalAlpha = alpha;
|
|
119
|
-
ctx.fillStyle = fill;
|
|
120
|
-
ctx.fill(path);
|
|
121
|
-
ctx.restore();
|
|
122
|
-
}
|
|
123
|
-
|
|
124
58
|
/** Draws one frame on a canvas `BOX` units square (scaled to its pixels). */
|
|
125
59
|
export function drawPose(ctx: CanvasRenderingContext2D, width: number, look: Look, pose: Pose): void {
|
|
126
|
-
const k = width / BOX;
|
|
127
60
|
const [violet, indigo, teal] = look.colours;
|
|
128
61
|
const p = shapes();
|
|
129
|
-
ctx
|
|
130
|
-
ctx.clearRect(0, 0, width, width);
|
|
131
|
-
ctx.setTransform(k, 0, 0, k, PAD * k, PAD * k);
|
|
62
|
+
begin(ctx, width);
|
|
132
63
|
if (look.variant === "logo") {
|
|
133
64
|
const ringA = (() => {
|
|
134
65
|
if (look.flat) return violet;
|
|
@@ -154,15 +85,15 @@ export function drawPose(ctx: CanvasRenderingContext2D, width: number, look: Loo
|
|
|
154
85
|
ctx.fillStyle = ringB;
|
|
155
86
|
ctx.fill(p.rb);
|
|
156
87
|
ctx.restore();
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
88
|
+
fillAround(ctx, C_BIG, pose.bigScale, pose.bigTurn, p.big, violet, 1);
|
|
89
|
+
fillAround(ctx, C_A, pose.twinkleScale, 0, p.a, indigo, pose.twinkleAlpha);
|
|
90
|
+
fillAround(ctx, C_B, pose.twinkleScale, 0, p.b, teal, pose.twinkleAlpha);
|
|
160
91
|
return;
|
|
161
92
|
}
|
|
162
93
|
ctx.translate(512, 512);
|
|
163
94
|
ctx.scale(1.45, 1.45);
|
|
164
95
|
ctx.translate(-512, -512);
|
|
165
|
-
|
|
96
|
+
fillAround(ctx, C_BIG, pose.bigScale, pose.bigTurn, p.big, violet, 1);
|
|
166
97
|
ctx.save();
|
|
167
98
|
ctx.translate(512, 512);
|
|
168
99
|
ctx.rotate((pose.swap * Math.PI) / 180);
|
|
@@ -173,77 +104,3 @@ export function drawPose(ctx: CanvasRenderingContext2D, width: number, look: Loo
|
|
|
173
104
|
ctx.fill(p.b);
|
|
174
105
|
ctx.restore();
|
|
175
106
|
}
|
|
176
|
-
|
|
177
|
-
/** A mark the loop draws. */
|
|
178
|
-
export interface Animated {
|
|
179
|
-
canvas: HTMLCanvasElement;
|
|
180
|
-
look: () => Look;
|
|
181
|
-
/** ms of animation shown so far, advanced by the loop. */
|
|
182
|
-
clock: number;
|
|
183
|
-
/** False while off screen: the clock still runs, nothing is drawn. */
|
|
184
|
-
visible: boolean;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
const marks = new Set<Animated>();
|
|
188
|
-
let frame = 0;
|
|
189
|
-
let last = 0;
|
|
190
|
-
|
|
191
|
-
/** Speed and pause from the nearest host that sets them. */
|
|
192
|
-
export function motionOf(el: Element): { speed: number; paused: boolean } {
|
|
193
|
-
const host = el.closest("[data-wp-motion-speed], [data-wp-motion-paused]");
|
|
194
|
-
if (!host) return { speed: 1, paused: false };
|
|
195
|
-
const paused = host.closest("[data-wp-motion-paused]") !== null;
|
|
196
|
-
const speedHost = host.closest("[data-wp-motion-speed]");
|
|
197
|
-
const speed = Number(speedHost?.getAttribute("data-wp-motion-speed") ?? "1");
|
|
198
|
-
return { speed: Number.isFinite(speed) && speed >= 0 ? speed : 1, paused };
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
function fit(c: HTMLCanvasElement): void {
|
|
202
|
-
const css = c.clientWidth;
|
|
203
|
-
const want = Math.max(1, Math.round(css * (window.devicePixelRatio || 1)));
|
|
204
|
-
if (c.width !== want) {
|
|
205
|
-
c.width = want;
|
|
206
|
-
c.height = want;
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
function tick(now: number): void {
|
|
211
|
-
const dt = last ? Math.min(now - last, 100) : 0;
|
|
212
|
-
last = now;
|
|
213
|
-
for (const m of marks) {
|
|
214
|
-
const { speed, paused } = motionOf(m.canvas);
|
|
215
|
-
if (!paused) m.clock += dt * speed;
|
|
216
|
-
if (!m.visible) continue;
|
|
217
|
-
const ctx = m.canvas.getContext("2d");
|
|
218
|
-
if (!ctx) continue;
|
|
219
|
-
fit(m.canvas);
|
|
220
|
-
drawPose(ctx, m.canvas.width, m.look(), poseAt(m.clock));
|
|
221
|
-
}
|
|
222
|
-
frame = marks.size ? requestAnimationFrame(tick) : 0;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
/** Starts drawing a mark; returns the function that stops it. */
|
|
226
|
-
export function animate(mark: Animated): () => void {
|
|
227
|
-
marks.add(mark);
|
|
228
|
-
if (!frame) {
|
|
229
|
-
last = 0;
|
|
230
|
-
frame = requestAnimationFrame(tick);
|
|
231
|
-
}
|
|
232
|
-
return () => {
|
|
233
|
-
marks.delete(mark);
|
|
234
|
-
if (!marks.size && frame) {
|
|
235
|
-
cancelAnimationFrame(frame);
|
|
236
|
-
frame = 0;
|
|
237
|
-
}
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/** Draws one still frame right away (the first frame, before the loop runs,
|
|
242
|
-
* so the mark never shows blank). */
|
|
243
|
-
export function drawNow(mark: Animated): boolean {
|
|
244
|
-
const ctx = mark.canvas.getContext("2d");
|
|
245
|
-
if (!ctx) return false;
|
|
246
|
-
fit(mark.canvas);
|
|
247
|
-
drawPose(ctx, mark.canvas.width, mark.look(), poseAt(mark.clock));
|
|
248
|
-
return true;
|
|
249
|
-
}
|
package/src/matrix-axis.ts
CHANGED
|
@@ -89,3 +89,31 @@ export function groupHue(grp: AxisGroup, role: "source" | "target", labeled: boo
|
|
|
89
89
|
if (!isBucket(grp)) return axisHueAt(grp.axisIndex);
|
|
90
90
|
return labeled ? UNGROUPED_HUE : role === "source" ? "var(--wp-constraint-source)" : "var(--wp-constraint-target)";
|
|
91
91
|
}
|
|
92
|
+
|
|
93
|
+
/** A constraint cell's rule. `only` (schema v6, linked picks): when the
|
|
94
|
+
* source fires, targets without a rule of their own in that row are
|
|
95
|
+
* excluded. `allow` is the neutral cell. */
|
|
96
|
+
export type CellMode = "allow" | "boost" | "reduce" | "exclude" | "only";
|
|
97
|
+
|
|
98
|
+
/** The glyph each rule draws in a matrix cell, a legend or a rules list. */
|
|
99
|
+
export const MODE_GLYPH: Record<CellMode, string> = {
|
|
100
|
+
only: "✓",
|
|
101
|
+
boost: "↑",
|
|
102
|
+
reduce: "↓",
|
|
103
|
+
exclude: "×",
|
|
104
|
+
allow: "·",
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
/** The word for each rule. */
|
|
108
|
+
export const MODE_LABEL: Record<CellMode, string> = {
|
|
109
|
+
boost: "Boost",
|
|
110
|
+
reduce: "Reduce",
|
|
111
|
+
exclude: "Exclude",
|
|
112
|
+
allow: "Neutral",
|
|
113
|
+
only: "Only",
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
/** A published mode string as a rule: anything unknown reads as neutral. */
|
|
117
|
+
export function normalizeMode(raw: string | null | undefined): CellMode {
|
|
118
|
+
return raw === "exclude" || raw === "boost" || raw === "reduce" || raw === "only" ? raw : "allow";
|
|
119
|
+
}
|
package/src/pi-icons.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Every PrimeIcons glyph in the installed `primeicons.css`, minus the `pi-`
|
|
3
|
+
* prefix: what IconPicker `all` offers (searchable), and what an app can
|
|
4
|
+
* check a typed `:pi-name:` against. IconPicker without `all` offers the
|
|
5
|
+
* curated groups in `icon-catalog.ts`. `pi-icons.test.ts` keeps this list
|
|
6
|
+
* equal to the stylesheet.
|
|
7
|
+
*/
|
|
8
|
+
export const PI_ICONS: readonly string[] = [
|
|
9
|
+
"address-book", "align-center", "align-justify", "align-left", "align-right", "amazon", "android", "angle-double-down",
|
|
10
|
+
"angle-double-left", "angle-double-right", "angle-double-up", "angle-down", "angle-left", "angle-right", "angle-up", "apple",
|
|
11
|
+
"arrow-circle-down", "arrow-circle-left", "arrow-circle-right", "arrow-circle-up", "arrow-down", "arrow-down-left", "arrow-down-left-and-arrow-up-right-to-center", "arrow-down-right",
|
|
12
|
+
"arrow-left", "arrow-right", "arrow-right-arrow-left", "arrow-up", "arrow-up-left", "arrow-up-right", "arrow-up-right-and-arrow-down-left-from-center", "arrows-alt",
|
|
13
|
+
"arrows-h", "arrows-v", "asterisk", "at", "backward", "ban", "barcode", "bars",
|
|
14
|
+
"bell", "bell-slash", "bitcoin", "bolt", "book", "bookmark", "bookmark-fill", "box",
|
|
15
|
+
"briefcase", "building", "building-columns", "bullseye", "calculator", "calendar", "calendar-clock", "calendar-minus",
|
|
16
|
+
"calendar-plus", "calendar-times", "camera", "car", "caret-down", "caret-left", "caret-right", "caret-up",
|
|
17
|
+
"cart-arrow-down", "cart-minus", "cart-plus", "chart-bar", "chart-line", "chart-pie", "chart-scatter", "check",
|
|
18
|
+
"check-circle", "check-square", "chevron-circle-down", "chevron-circle-left", "chevron-circle-right", "chevron-circle-up", "chevron-down", "chevron-left",
|
|
19
|
+
"chevron-right", "chevron-up", "circle", "circle-fill", "circle-off", "circle-on", "clipboard", "clock",
|
|
20
|
+
"clone", "cloud", "cloud-download", "cloud-upload", "code", "cog", "comment", "comments",
|
|
21
|
+
"compass", "copy", "credit-card", "crown", "database", "delete-left", "desktop", "directions",
|
|
22
|
+
"directions-alt", "discord", "dollar", "download", "eject", "ellipsis-h", "ellipsis-v", "envelope",
|
|
23
|
+
"equals", "eraser", "ethereum", "euro", "exclamation-circle", "exclamation-triangle", "expand", "external-link",
|
|
24
|
+
"eye", "eye-slash", "face-smile", "facebook", "fast-backward", "fast-forward", "file", "file-arrow-up",
|
|
25
|
+
"file-check", "file-edit", "file-excel", "file-export", "file-import", "file-o", "file-pdf", "file-plus",
|
|
26
|
+
"file-word", "filter", "filter-fill", "filter-slash", "flag", "flag-fill", "folder", "folder-open",
|
|
27
|
+
"folder-plus", "forward", "gauge", "gift", "github", "globe", "google", "graduation-cap",
|
|
28
|
+
"hammer", "hashtag", "headphones", "heart", "heart-fill", "history", "home", "hourglass",
|
|
29
|
+
"id-card", "image", "images", "inbox", "indian-rupee", "info", "info-circle", "instagram",
|
|
30
|
+
"key", "language", "lightbulb", "link", "linkedin", "list", "list-check", "lock",
|
|
31
|
+
"lock-open", "map", "map-marker", "mars", "megaphone", "microchip", "microchip-ai", "microphone",
|
|
32
|
+
"microsoft", "minus", "minus-circle", "mobile", "money-bill", "moon", "objects-column", "palette",
|
|
33
|
+
"paperclip", "pause", "pause-circle", "paypal", "pen-to-square", "pencil", "percentage", "phone",
|
|
34
|
+
"pinterest", "play", "play-circle", "plus", "plus-circle", "pound", "power-off", "prime",
|
|
35
|
+
"print", "qrcode", "question", "question-circle", "receipt", "reddit", "refresh", "replay",
|
|
36
|
+
"reply", "save", "search", "search-minus", "search-plus", "send", "server", "share-alt",
|
|
37
|
+
"shield", "shop", "shopping-bag", "shopping-cart", "sign-in", "sign-out", "sitemap", "slack",
|
|
38
|
+
"sliders-h", "sliders-v", "sort", "sort-alpha-down", "sort-alpha-down-alt", "sort-alpha-up", "sort-alpha-up-alt", "sort-alt",
|
|
39
|
+
"sort-alt-slash", "sort-amount-down", "sort-amount-down-alt", "sort-amount-up", "sort-amount-up-alt", "sort-down", "sort-down-fill", "sort-numeric-down",
|
|
40
|
+
"sort-numeric-down-alt", "sort-numeric-up", "sort-numeric-up-alt", "sort-up", "sort-up-fill", "sparkles", "spinner", "spinner-dotted",
|
|
41
|
+
"star", "star-fill", "star-half", "star-half-fill", "step-backward", "step-backward-alt", "step-forward", "step-forward-alt",
|
|
42
|
+
"stop", "stop-circle", "stopwatch", "sun", "sync", "table", "tablet", "tag",
|
|
43
|
+
"tags", "telegram", "th-large", "thumbs-down", "thumbs-down-fill", "thumbs-up", "thumbs-up-fill", "thumbtack",
|
|
44
|
+
"ticket", "tiktok", "times", "times-circle", "trash", "trophy", "truck", "turkish-lira",
|
|
45
|
+
"twitch", "twitter", "undo", "unlock", "upload", "user", "user-edit", "user-minus",
|
|
46
|
+
"user-plus", "users", "venus", "verified", "video", "vimeo", "volume-down", "volume-off",
|
|
47
|
+
"volume-up", "wallet", "warehouse", "wave-pulse", "whatsapp", "wifi", "window-maximize", "window-minimize",
|
|
48
|
+
"wrench", "youtube",
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
export const PI_ICON_SET: ReadonlySet<string> = new Set(PI_ICONS);
|