@graphrefly/graphrefly 0.24.0 → 0.25.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/dist/{chunk-IPLKX3L2.js → chunk-EVR6UFUV.js} +2 -2
- package/dist/{chunk-5WGT55R4.js → chunk-IAHGTNOZ.js} +4 -2
- package/dist/{chunk-5WGT55R4.js.map → chunk-IAHGTNOZ.js.map} +1 -1
- package/dist/{chunk-AOCBDH4T.js → chunk-L2GLW2U7.js} +68 -1
- package/dist/chunk-L2GLW2U7.js.map +1 -0
- package/dist/{chunk-TDEXAMGO.js → chunk-TKE3JGOH.js} +488 -16
- package/dist/chunk-TKE3JGOH.js.map +1 -0
- package/dist/compat/nestjs/index.cjs.map +1 -1
- package/dist/compat/nestjs/index.js +2 -2
- package/dist/extra/index.cjs +68 -0
- package/dist/extra/index.cjs.map +1 -1
- package/dist/extra/index.d.cts +1 -1
- package/dist/extra/index.d.ts +1 -1
- package/dist/extra/index.js +4 -2
- package/dist/{index-1z8vRTCt.d.cts → index-Ch0IpIO0.d.cts} +29 -2
- package/dist/{index-b5BYtczN.d.cts → index-DKE1EATr.d.cts} +222 -2
- package/dist/{index-BysCTzJz.d.ts → index-Ds23Wvou.d.ts} +29 -2
- package/dist/{index-D7XgsUt7.d.ts → index-OXImXMq6.d.ts} +222 -2
- package/dist/index.cjs +550 -15
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +6 -4
- package/dist/index.js.map +1 -1
- package/dist/patterns/reactive-layout/index.cjs +488 -16
- package/dist/patterns/reactive-layout/index.cjs.map +1 -1
- package/dist/patterns/reactive-layout/index.d.cts +1 -1
- package/dist/patterns/reactive-layout/index.d.ts +1 -1
- package/dist/patterns/reactive-layout/index.js +16 -4
- package/package.json +1 -1
- package/dist/chunk-AOCBDH4T.js.map +0 -1
- package/dist/chunk-TDEXAMGO.js.map +0 -1
- /package/dist/{chunk-IPLKX3L2.js.map → chunk-EVR6UFUV.js.map} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -200,6 +200,7 @@ __export(index_exports, {
|
|
|
200
200
|
fromPromise: () => fromPromise,
|
|
201
201
|
fromPulsar: () => fromPulsar,
|
|
202
202
|
fromRabbitMQ: () => fromRabbitMQ,
|
|
203
|
+
fromRaf: () => fromRaf,
|
|
203
204
|
fromRedisStream: () => fromRedisStream,
|
|
204
205
|
fromSSE: () => fromSSE,
|
|
205
206
|
fromSqlite: () => fromSqlite,
|
|
@@ -3186,6 +3187,72 @@ function fromTimer(ms, opts) {
|
|
|
3186
3187
|
return cleanup;
|
|
3187
3188
|
}, sourceOpts(rest));
|
|
3188
3189
|
}
|
|
3190
|
+
function fromRaf(opts) {
|
|
3191
|
+
const { signal, ...rest } = opts ?? {};
|
|
3192
|
+
return producer((a) => {
|
|
3193
|
+
let done = false;
|
|
3194
|
+
let rafId;
|
|
3195
|
+
let fallbackTimer;
|
|
3196
|
+
let abortListenerAdded = false;
|
|
3197
|
+
let visibilityListenerAdded = false;
|
|
3198
|
+
const raf = typeof requestAnimationFrame === "function" ? requestAnimationFrame : void 0;
|
|
3199
|
+
const caf = typeof cancelAnimationFrame === "function" ? cancelAnimationFrame : void 0;
|
|
3200
|
+
const doc = typeof document !== "undefined" ? document : void 0;
|
|
3201
|
+
const clearPending = () => {
|
|
3202
|
+
if (rafId !== void 0 && caf) caf(rafId);
|
|
3203
|
+
if (fallbackTimer !== void 0) clearTimeout(fallbackTimer);
|
|
3204
|
+
rafId = void 0;
|
|
3205
|
+
fallbackTimer = void 0;
|
|
3206
|
+
};
|
|
3207
|
+
const cleanup = () => {
|
|
3208
|
+
done = true;
|
|
3209
|
+
clearPending();
|
|
3210
|
+
if (abortListenerAdded) {
|
|
3211
|
+
signal?.removeEventListener("abort", onAbort);
|
|
3212
|
+
abortListenerAdded = false;
|
|
3213
|
+
}
|
|
3214
|
+
if (visibilityListenerAdded && doc) {
|
|
3215
|
+
doc.removeEventListener("visibilitychange", onVisibilityChange);
|
|
3216
|
+
visibilityListenerAdded = false;
|
|
3217
|
+
}
|
|
3218
|
+
};
|
|
3219
|
+
const onAbort = () => {
|
|
3220
|
+
if (done) return;
|
|
3221
|
+
cleanup();
|
|
3222
|
+
a.down([[ERROR, signal.reason]]);
|
|
3223
|
+
};
|
|
3224
|
+
const tick = (now) => {
|
|
3225
|
+
if (done) return;
|
|
3226
|
+
a.emit(now);
|
|
3227
|
+
scheduleNext();
|
|
3228
|
+
};
|
|
3229
|
+
const scheduleNext = () => {
|
|
3230
|
+
if (done) return;
|
|
3231
|
+
if (raf && (!doc || doc.visibilityState !== "hidden")) {
|
|
3232
|
+
rafId = raf(tick);
|
|
3233
|
+
} else {
|
|
3234
|
+
fallbackTimer = setTimeout(() => tick(performance.now()), 16);
|
|
3235
|
+
}
|
|
3236
|
+
};
|
|
3237
|
+
const onVisibilityChange = () => {
|
|
3238
|
+
if (done) return;
|
|
3239
|
+
clearPending();
|
|
3240
|
+
scheduleNext();
|
|
3241
|
+
};
|
|
3242
|
+
if (signal?.aborted) {
|
|
3243
|
+
onAbort();
|
|
3244
|
+
return cleanup;
|
|
3245
|
+
}
|
|
3246
|
+
signal?.addEventListener("abort", onAbort, { once: true });
|
|
3247
|
+
abortListenerAdded = signal !== void 0;
|
|
3248
|
+
if (doc && raf) {
|
|
3249
|
+
doc.addEventListener("visibilitychange", onVisibilityChange);
|
|
3250
|
+
visibilityListenerAdded = true;
|
|
3251
|
+
}
|
|
3252
|
+
scheduleNext();
|
|
3253
|
+
return cleanup;
|
|
3254
|
+
}, sourceOpts(rest));
|
|
3255
|
+
}
|
|
3189
3256
|
function fromCron(expr, opts) {
|
|
3190
3257
|
const schedule = parseCron(expr);
|
|
3191
3258
|
const { tickMs: tickOpt, output, ...rest } = opts ?? {};
|
|
@@ -8368,6 +8435,7 @@ __export(extra_exports, {
|
|
|
8368
8435
|
fromPromise: () => fromPromise,
|
|
8369
8436
|
fromPulsar: () => fromPulsar,
|
|
8370
8437
|
fromRabbitMQ: () => fromRabbitMQ,
|
|
8438
|
+
fromRaf: () => fromRaf,
|
|
8371
8439
|
fromRedisStream: () => fromRedisStream,
|
|
8372
8440
|
fromSSE: () => fromSSE,
|
|
8373
8441
|
fromSqlite: () => fromSqlite,
|
|
@@ -18054,7 +18122,7 @@ function analyzeAndMeasure(text, font, adapter, cache, stats) {
|
|
|
18054
18122
|
const normalized = normalizeWhitespace(text);
|
|
18055
18123
|
if (normalized.length === 0) return [];
|
|
18056
18124
|
const pieces = segmentText(normalized);
|
|
18057
|
-
const
|
|
18125
|
+
const graphemeSegmenter2 = new Intl.Segmenter(void 0, {
|
|
18058
18126
|
granularity: "grapheme"
|
|
18059
18127
|
});
|
|
18060
18128
|
const rawTexts = [];
|
|
@@ -18098,7 +18166,8 @@ function analyzeAndMeasure(text, font, adapter, cache, stats) {
|
|
|
18098
18166
|
let w = fontCache.get(seg);
|
|
18099
18167
|
if (w === void 0) {
|
|
18100
18168
|
if (stats) stats.misses += 1;
|
|
18101
|
-
|
|
18169
|
+
const raw = adapter.measureSegment(seg, font).width;
|
|
18170
|
+
w = Number.isFinite(raw) && raw >= 0 ? raw : 0;
|
|
18102
18171
|
fontCache.set(seg, w);
|
|
18103
18172
|
} else if (stats) {
|
|
18104
18173
|
stats.hits += 1;
|
|
@@ -18120,7 +18189,7 @@ function analyzeAndMeasure(text, font, adapter, cache, stats) {
|
|
|
18120
18189
|
}
|
|
18121
18190
|
if (isCJK(t)) {
|
|
18122
18191
|
let unitText = "";
|
|
18123
|
-
for (const gs of
|
|
18192
|
+
for (const gs of graphemeSegmenter2.segment(t)) {
|
|
18124
18193
|
const grapheme = gs.segment;
|
|
18125
18194
|
if (unitText.length > 0 && kinsokuStart.has(grapheme)) {
|
|
18126
18195
|
unitText += grapheme;
|
|
@@ -18152,7 +18221,7 @@ function analyzeAndMeasure(text, font, adapter, cache, stats) {
|
|
|
18152
18221
|
let graphemeWidths = null;
|
|
18153
18222
|
if (mergedWordLike[i] && t.length > 1) {
|
|
18154
18223
|
const gWidths = [];
|
|
18155
|
-
for (const gs of
|
|
18224
|
+
for (const gs of graphemeSegmenter2.segment(t)) {
|
|
18156
18225
|
gWidths.push(measureCached(gs.segment));
|
|
18157
18226
|
}
|
|
18158
18227
|
if (gWidths.length > 1) {
|
|
@@ -18192,10 +18261,10 @@ function computeLineBreaks(segments, maxWidth, adapter, font, cache) {
|
|
|
18192
18261
|
const seg = segments[i];
|
|
18193
18262
|
if (seg.kind === "soft-hyphen" || seg.kind === "hard-break") continue;
|
|
18194
18263
|
if (i === lineStartSeg && lineStartGrapheme > 0 && seg.graphemeWidths) {
|
|
18195
|
-
const
|
|
18264
|
+
const graphemeSegmenter2 = new Intl.Segmenter(void 0, {
|
|
18196
18265
|
granularity: "grapheme"
|
|
18197
18266
|
});
|
|
18198
|
-
const graphemes = [...
|
|
18267
|
+
const graphemes = [...graphemeSegmenter2.segment(seg.text)].map((g) => g.segment);
|
|
18199
18268
|
text += graphemes.slice(lineStartGrapheme).join("");
|
|
18200
18269
|
} else {
|
|
18201
18270
|
text += seg.text;
|
|
@@ -18203,10 +18272,10 @@ function computeLineBreaks(segments, maxWidth, adapter, font, cache) {
|
|
|
18203
18272
|
}
|
|
18204
18273
|
if (endGrapheme > 0 && endSeg < segments.length) {
|
|
18205
18274
|
const seg = segments[endSeg];
|
|
18206
|
-
const
|
|
18275
|
+
const graphemeSegmenter2 = new Intl.Segmenter(void 0, {
|
|
18207
18276
|
granularity: "grapheme"
|
|
18208
18277
|
});
|
|
18209
|
-
const graphemes = [...
|
|
18278
|
+
const graphemes = [...graphemeSegmenter2.segment(seg.text)].map((g) => g.segment);
|
|
18210
18279
|
const startG = lineStartSeg === endSeg ? lineStartGrapheme : 0;
|
|
18211
18280
|
text += graphemes.slice(startG, endGrapheme).join("");
|
|
18212
18281
|
}
|
|
@@ -18226,7 +18295,7 @@ function computeLineBreaks(segments, maxWidth, adapter, font, cache) {
|
|
|
18226
18295
|
pendingBreakSeg = -1;
|
|
18227
18296
|
pendingBreakWidth = 0;
|
|
18228
18297
|
}
|
|
18229
|
-
function
|
|
18298
|
+
function canBreakAfter2(kind) {
|
|
18230
18299
|
return kind === "space" || kind === "zero-width-break" || kind === "soft-hyphen";
|
|
18231
18300
|
}
|
|
18232
18301
|
function startLine(segIdx, graphemeIdx, width) {
|
|
@@ -18271,7 +18340,7 @@ function computeLineBreaks(segments, maxWidth, adapter, font, cache) {
|
|
|
18271
18340
|
} else {
|
|
18272
18341
|
startLine(i, 0, w);
|
|
18273
18342
|
}
|
|
18274
|
-
if (
|
|
18343
|
+
if (canBreakAfter2(seg.kind)) {
|
|
18275
18344
|
pendingBreakSeg = i + 1;
|
|
18276
18345
|
pendingBreakWidth = seg.kind === "space" ? lineW - w : lineW;
|
|
18277
18346
|
}
|
|
@@ -18279,7 +18348,7 @@ function computeLineBreaks(segments, maxWidth, adapter, font, cache) {
|
|
|
18279
18348
|
}
|
|
18280
18349
|
const newW = lineW + w;
|
|
18281
18350
|
if (newW > maxWidth + 5e-3) {
|
|
18282
|
-
if (
|
|
18351
|
+
if (canBreakAfter2(seg.kind)) {
|
|
18283
18352
|
lineW += w;
|
|
18284
18353
|
lineEndSeg = i + 1;
|
|
18285
18354
|
lineEndGrapheme = 0;
|
|
@@ -18303,7 +18372,7 @@ function computeLineBreaks(segments, maxWidth, adapter, font, cache) {
|
|
|
18303
18372
|
lineW = newW;
|
|
18304
18373
|
lineEndSeg = i + 1;
|
|
18305
18374
|
lineEndGrapheme = 0;
|
|
18306
|
-
if (
|
|
18375
|
+
if (canBreakAfter2(seg.kind)) {
|
|
18307
18376
|
pendingBreakSeg = i + 1;
|
|
18308
18377
|
pendingBreakWidth = seg.kind === "space" ? lineW - w : lineW;
|
|
18309
18378
|
}
|
|
@@ -18334,9 +18403,289 @@ function computeLineBreaks(segments, maxWidth, adapter, font, cache) {
|
|
|
18334
18403
|
}
|
|
18335
18404
|
}
|
|
18336
18405
|
}
|
|
18406
|
+
function canBreakAfter(kind) {
|
|
18407
|
+
return kind === "space" || kind === "zero-width-break" || kind === "soft-hyphen";
|
|
18408
|
+
}
|
|
18409
|
+
var _graphemeSegmenter = null;
|
|
18410
|
+
function graphemeSegmenter() {
|
|
18411
|
+
if (_graphemeSegmenter === null) {
|
|
18412
|
+
_graphemeSegmenter = new Intl.Segmenter(void 0, { granularity: "grapheme" });
|
|
18413
|
+
}
|
|
18414
|
+
return _graphemeSegmenter;
|
|
18415
|
+
}
|
|
18416
|
+
function sliceSegmentText(seg, startG, endG) {
|
|
18417
|
+
if (startG === 0 && endG < 0) return seg.text;
|
|
18418
|
+
const graphemes = [...graphemeSegmenter().segment(seg.text)].map((g) => g.segment);
|
|
18419
|
+
const stop = endG < 0 ? graphemes.length : endG;
|
|
18420
|
+
return graphemes.slice(startG, stop).join("");
|
|
18421
|
+
}
|
|
18422
|
+
function buildLineText(segments, startSeg, startG, endSeg, endG, appendHyphen) {
|
|
18423
|
+
let text = "";
|
|
18424
|
+
for (let i = startSeg; i < endSeg; i++) {
|
|
18425
|
+
const seg = segments[i];
|
|
18426
|
+
if (seg.kind === "soft-hyphen" || seg.kind === "hard-break") continue;
|
|
18427
|
+
if (i === startSeg && startG > 0) {
|
|
18428
|
+
text += sliceSegmentText(seg, startG, -1);
|
|
18429
|
+
} else {
|
|
18430
|
+
text += seg.text;
|
|
18431
|
+
}
|
|
18432
|
+
}
|
|
18433
|
+
if (endG > 0 && endSeg < segments.length) {
|
|
18434
|
+
const seg = segments[endSeg];
|
|
18435
|
+
const from = startSeg === endSeg ? startG : 0;
|
|
18436
|
+
text += sliceSegmentText(seg, from, endG);
|
|
18437
|
+
}
|
|
18438
|
+
if (appendHyphen) text += "-";
|
|
18439
|
+
return text;
|
|
18440
|
+
}
|
|
18441
|
+
function resolveHyphenWidth(ctx) {
|
|
18442
|
+
if (!ctx || !ctx.adapter || !ctx.font) return 0;
|
|
18443
|
+
const cache = ctx.cache;
|
|
18444
|
+
if (cache) {
|
|
18445
|
+
let fc = cache.get(ctx.font);
|
|
18446
|
+
if (!fc) {
|
|
18447
|
+
fc = /* @__PURE__ */ new Map();
|
|
18448
|
+
cache.set(ctx.font, fc);
|
|
18449
|
+
}
|
|
18450
|
+
let hw = fc.get("-");
|
|
18451
|
+
if (hw === void 0) {
|
|
18452
|
+
hw = ctx.adapter.measureSegment("-", ctx.font).width;
|
|
18453
|
+
fc.set("-", hw);
|
|
18454
|
+
}
|
|
18455
|
+
return hw;
|
|
18456
|
+
}
|
|
18457
|
+
return ctx.adapter.measureSegment("-", ctx.font).width;
|
|
18458
|
+
}
|
|
18459
|
+
function layoutNextLine(segments, cursor, slotWidth, ctx) {
|
|
18460
|
+
let i = cursor.segmentIndex;
|
|
18461
|
+
const initialG = cursor.graphemeIndex;
|
|
18462
|
+
if (i >= segments.length) return null;
|
|
18463
|
+
if (initialG === 0) {
|
|
18464
|
+
while (i < segments.length) {
|
|
18465
|
+
const seg = segments[i];
|
|
18466
|
+
if (seg.kind === "hard-break") {
|
|
18467
|
+
return {
|
|
18468
|
+
text: "",
|
|
18469
|
+
width: 0,
|
|
18470
|
+
start: { segmentIndex: cursor.segmentIndex, graphemeIndex: 0 },
|
|
18471
|
+
end: { segmentIndex: i + 1, graphemeIndex: 0 }
|
|
18472
|
+
};
|
|
18473
|
+
}
|
|
18474
|
+
if (seg.kind === "space" || seg.kind === "zero-width-break" || seg.kind === "soft-hyphen") {
|
|
18475
|
+
i += 1;
|
|
18476
|
+
continue;
|
|
18477
|
+
}
|
|
18478
|
+
break;
|
|
18479
|
+
}
|
|
18480
|
+
if (i >= segments.length) return null;
|
|
18481
|
+
}
|
|
18482
|
+
const hyphenWidth = resolveHyphenWidth(ctx);
|
|
18483
|
+
const startSeg = i;
|
|
18484
|
+
const startG = i === cursor.segmentIndex ? initialG : 0;
|
|
18485
|
+
let lineW = 0;
|
|
18486
|
+
let lineEndSeg = startSeg;
|
|
18487
|
+
let lineEndG = 0;
|
|
18488
|
+
let hasContent = false;
|
|
18489
|
+
let pendingBreakSeg = -1;
|
|
18490
|
+
let pendingBreakG = 0;
|
|
18491
|
+
let pendingBreakWidth = 0;
|
|
18492
|
+
let pendingBreakSoftHyphen = false;
|
|
18493
|
+
const recordPending = (sIdx, gIdx, widthAtBreak, kind) => {
|
|
18494
|
+
pendingBreakSeg = sIdx;
|
|
18495
|
+
pendingBreakG = gIdx;
|
|
18496
|
+
pendingBreakWidth = widthAtBreak;
|
|
18497
|
+
pendingBreakSoftHyphen = kind === "soft-hyphen";
|
|
18498
|
+
};
|
|
18499
|
+
const consumeBreakable = (segIdx, gStart, gWidths) => {
|
|
18500
|
+
for (let g = gStart; g < gWidths.length; g++) {
|
|
18501
|
+
const gw = gWidths[g];
|
|
18502
|
+
if (!hasContent) {
|
|
18503
|
+
lineW = gw;
|
|
18504
|
+
lineEndSeg = segIdx;
|
|
18505
|
+
lineEndG = g + 1;
|
|
18506
|
+
hasContent = true;
|
|
18507
|
+
continue;
|
|
18508
|
+
}
|
|
18509
|
+
if (lineW + gw > slotWidth + 5e-3) {
|
|
18510
|
+
return true;
|
|
18511
|
+
}
|
|
18512
|
+
lineW += gw;
|
|
18513
|
+
lineEndSeg = segIdx;
|
|
18514
|
+
lineEndG = g + 1;
|
|
18515
|
+
}
|
|
18516
|
+
if (lineEndSeg === segIdx && lineEndG === gWidths.length) {
|
|
18517
|
+
lineEndSeg = segIdx + 1;
|
|
18518
|
+
lineEndG = 0;
|
|
18519
|
+
}
|
|
18520
|
+
return false;
|
|
18521
|
+
};
|
|
18522
|
+
if (startG > 0 && startSeg < segments.length) {
|
|
18523
|
+
const seg = segments[startSeg];
|
|
18524
|
+
if (seg.graphemeWidths) {
|
|
18525
|
+
const overflowed = consumeBreakable(startSeg, startG, seg.graphemeWidths);
|
|
18526
|
+
if (overflowed) {
|
|
18527
|
+
const text2 = buildLineText(segments, startSeg, startG, lineEndSeg, lineEndG, false);
|
|
18528
|
+
return {
|
|
18529
|
+
text: text2,
|
|
18530
|
+
width: lineW,
|
|
18531
|
+
start: { segmentIndex: startSeg, graphemeIndex: startG },
|
|
18532
|
+
end: { segmentIndex: lineEndSeg, graphemeIndex: lineEndG }
|
|
18533
|
+
};
|
|
18534
|
+
}
|
|
18535
|
+
i = lineEndSeg;
|
|
18536
|
+
} else {
|
|
18537
|
+
}
|
|
18538
|
+
}
|
|
18539
|
+
for (; i < segments.length; ) {
|
|
18540
|
+
const seg = segments[i];
|
|
18541
|
+
if (seg.kind === "hard-break") {
|
|
18542
|
+
if (hasContent) {
|
|
18543
|
+
const endsAtSoftHyphen2 = lineEndSeg > 0 && segments[lineEndSeg - 1]?.kind === "soft-hyphen";
|
|
18544
|
+
const text2 = buildLineText(
|
|
18545
|
+
segments,
|
|
18546
|
+
startSeg,
|
|
18547
|
+
startG,
|
|
18548
|
+
lineEndSeg,
|
|
18549
|
+
lineEndG,
|
|
18550
|
+
endsAtSoftHyphen2
|
|
18551
|
+
);
|
|
18552
|
+
return {
|
|
18553
|
+
text: text2,
|
|
18554
|
+
width: lineW + (endsAtSoftHyphen2 ? hyphenWidth : 0),
|
|
18555
|
+
start: { segmentIndex: startSeg, graphemeIndex: startG },
|
|
18556
|
+
end: { segmentIndex: lineEndSeg, graphemeIndex: lineEndG }
|
|
18557
|
+
};
|
|
18558
|
+
}
|
|
18559
|
+
return {
|
|
18560
|
+
text: "",
|
|
18561
|
+
width: 0,
|
|
18562
|
+
start: { segmentIndex: startSeg, graphemeIndex: startG },
|
|
18563
|
+
end: { segmentIndex: i + 1, graphemeIndex: 0 }
|
|
18564
|
+
};
|
|
18565
|
+
}
|
|
18566
|
+
const w = seg.width;
|
|
18567
|
+
if (!hasContent) {
|
|
18568
|
+
if (w > slotWidth && seg.graphemeWidths) {
|
|
18569
|
+
const overflowed = consumeBreakable(i, 0, seg.graphemeWidths);
|
|
18570
|
+
if (overflowed) {
|
|
18571
|
+
const text2 = buildLineText(segments, startSeg, startG, lineEndSeg, lineEndG, false);
|
|
18572
|
+
return {
|
|
18573
|
+
text: text2,
|
|
18574
|
+
width: lineW,
|
|
18575
|
+
start: { segmentIndex: startSeg, graphemeIndex: startG },
|
|
18576
|
+
end: { segmentIndex: lineEndSeg, graphemeIndex: lineEndG }
|
|
18577
|
+
};
|
|
18578
|
+
}
|
|
18579
|
+
i = lineEndSeg;
|
|
18580
|
+
continue;
|
|
18581
|
+
}
|
|
18582
|
+
lineW = w;
|
|
18583
|
+
lineEndSeg = i + 1;
|
|
18584
|
+
lineEndG = 0;
|
|
18585
|
+
hasContent = true;
|
|
18586
|
+
if (canBreakAfter(seg.kind)) {
|
|
18587
|
+
recordPending(i + 1, 0, seg.kind === "space" ? lineW - w : lineW, seg.kind);
|
|
18588
|
+
}
|
|
18589
|
+
i += 1;
|
|
18590
|
+
continue;
|
|
18591
|
+
}
|
|
18592
|
+
const newW = lineW + w;
|
|
18593
|
+
if (newW > slotWidth + 5e-3) {
|
|
18594
|
+
if (canBreakAfter(seg.kind)) {
|
|
18595
|
+
lineEndSeg = i + 1;
|
|
18596
|
+
lineEndG = 0;
|
|
18597
|
+
const endsAtSoftHyphen2 = seg.kind === "soft-hyphen";
|
|
18598
|
+
const finalWidth = seg.kind === "space" ? lineW : lineW + (endsAtSoftHyphen2 ? hyphenWidth : 0);
|
|
18599
|
+
const text3 = buildLineText(
|
|
18600
|
+
segments,
|
|
18601
|
+
startSeg,
|
|
18602
|
+
startG,
|
|
18603
|
+
lineEndSeg,
|
|
18604
|
+
lineEndG,
|
|
18605
|
+
endsAtSoftHyphen2
|
|
18606
|
+
);
|
|
18607
|
+
return {
|
|
18608
|
+
text: text3,
|
|
18609
|
+
width: finalWidth,
|
|
18610
|
+
start: { segmentIndex: startSeg, graphemeIndex: startG },
|
|
18611
|
+
end: { segmentIndex: lineEndSeg, graphemeIndex: lineEndG }
|
|
18612
|
+
};
|
|
18613
|
+
}
|
|
18614
|
+
if (pendingBreakSeg >= 0) {
|
|
18615
|
+
const text3 = buildLineText(
|
|
18616
|
+
segments,
|
|
18617
|
+
startSeg,
|
|
18618
|
+
startG,
|
|
18619
|
+
pendingBreakSeg,
|
|
18620
|
+
pendingBreakG,
|
|
18621
|
+
pendingBreakSoftHyphen
|
|
18622
|
+
);
|
|
18623
|
+
return {
|
|
18624
|
+
text: text3,
|
|
18625
|
+
width: pendingBreakWidth + (pendingBreakSoftHyphen ? hyphenWidth : 0),
|
|
18626
|
+
start: { segmentIndex: startSeg, graphemeIndex: startG },
|
|
18627
|
+
end: { segmentIndex: pendingBreakSeg, graphemeIndex: pendingBreakG }
|
|
18628
|
+
};
|
|
18629
|
+
}
|
|
18630
|
+
if (w > slotWidth && seg.graphemeWidths) {
|
|
18631
|
+
const text3 = buildLineText(segments, startSeg, startG, lineEndSeg, lineEndG, false);
|
|
18632
|
+
return {
|
|
18633
|
+
text: text3,
|
|
18634
|
+
width: lineW,
|
|
18635
|
+
start: { segmentIndex: startSeg, graphemeIndex: startG },
|
|
18636
|
+
end: { segmentIndex: lineEndSeg, graphemeIndex: lineEndG }
|
|
18637
|
+
};
|
|
18638
|
+
}
|
|
18639
|
+
const text2 = buildLineText(segments, startSeg, startG, lineEndSeg, lineEndG, false);
|
|
18640
|
+
return {
|
|
18641
|
+
text: text2,
|
|
18642
|
+
width: lineW,
|
|
18643
|
+
start: { segmentIndex: startSeg, graphemeIndex: startG },
|
|
18644
|
+
end: { segmentIndex: lineEndSeg, graphemeIndex: lineEndG }
|
|
18645
|
+
};
|
|
18646
|
+
}
|
|
18647
|
+
lineW = newW;
|
|
18648
|
+
lineEndSeg = i + 1;
|
|
18649
|
+
lineEndG = 0;
|
|
18650
|
+
if (canBreakAfter(seg.kind)) {
|
|
18651
|
+
recordPending(i + 1, 0, seg.kind === "space" ? lineW - w : lineW, seg.kind);
|
|
18652
|
+
}
|
|
18653
|
+
i += 1;
|
|
18654
|
+
}
|
|
18655
|
+
if (!hasContent) return null;
|
|
18656
|
+
const endsAtSoftHyphen = lineEndSeg > 0 && segments[lineEndSeg - 1]?.kind === "soft-hyphen";
|
|
18657
|
+
const text = buildLineText(segments, startSeg, startG, lineEndSeg, lineEndG, endsAtSoftHyphen);
|
|
18658
|
+
return {
|
|
18659
|
+
text,
|
|
18660
|
+
width: lineW + (endsAtSoftHyphen ? hyphenWidth : 0),
|
|
18661
|
+
start: { segmentIndex: startSeg, graphemeIndex: startG },
|
|
18662
|
+
end: { segmentIndex: lineEndSeg, graphemeIndex: lineEndG }
|
|
18663
|
+
};
|
|
18664
|
+
}
|
|
18665
|
+
function carveTextLineSlots(base, blocked, minSlotWidth = 0) {
|
|
18666
|
+
let slots = [base];
|
|
18667
|
+
for (let bi = 0; bi < blocked.length; bi++) {
|
|
18668
|
+
const block = blocked[bi];
|
|
18669
|
+
const next = [];
|
|
18670
|
+
for (let si = 0; si < slots.length; si++) {
|
|
18671
|
+
const slot = slots[si];
|
|
18672
|
+
if (block.right <= slot.left || block.left >= slot.right) {
|
|
18673
|
+
next.push(slot);
|
|
18674
|
+
continue;
|
|
18675
|
+
}
|
|
18676
|
+
if (block.left > slot.left) next.push({ left: slot.left, right: block.left });
|
|
18677
|
+
if (block.right < slot.right) next.push({ left: block.right, right: slot.right });
|
|
18678
|
+
}
|
|
18679
|
+
slots = next;
|
|
18680
|
+
}
|
|
18681
|
+
if (minSlotWidth > 0) {
|
|
18682
|
+
return slots.filter((s) => s.right - s.left >= minSlotWidth);
|
|
18683
|
+
}
|
|
18684
|
+
return slots;
|
|
18685
|
+
}
|
|
18337
18686
|
function computeCharPositions(lineBreaks, segments, lineHeight) {
|
|
18338
18687
|
const positions = [];
|
|
18339
|
-
const
|
|
18688
|
+
const graphemeSegmenter2 = new Intl.Segmenter(void 0, {
|
|
18340
18689
|
granularity: "grapheme"
|
|
18341
18690
|
});
|
|
18342
18691
|
for (let lineIdx = 0; lineIdx < lineBreaks.lines.length; lineIdx++) {
|
|
@@ -18349,7 +18698,7 @@ function computeCharPositions(lineBreaks, segments, lineHeight) {
|
|
|
18349
18698
|
if (si >= line.endSegment && line.endGrapheme === 0) break;
|
|
18350
18699
|
continue;
|
|
18351
18700
|
}
|
|
18352
|
-
const graphemes = [...
|
|
18701
|
+
const graphemes = [...graphemeSegmenter2.segment(seg.text)].map((g) => g.segment);
|
|
18353
18702
|
if (graphemes.length === 0) continue;
|
|
18354
18703
|
const startG = si === line.startSegment ? line.startGrapheme : 0;
|
|
18355
18704
|
let endG;
|
|
@@ -21340,14 +21689,20 @@ __export(reactive_layout_exports, {
|
|
|
21340
21689
|
PrecomputedAdapter: () => PrecomputedAdapter,
|
|
21341
21690
|
SvgBoundsAdapter: () => SvgBoundsAdapter,
|
|
21342
21691
|
analyzeAndMeasure: () => analyzeAndMeasure,
|
|
21692
|
+
carveTextLineSlots: () => carveTextLineSlots,
|
|
21693
|
+
circleIntervalForBand: () => circleIntervalForBand,
|
|
21343
21694
|
computeBlockFlow: () => computeBlockFlow,
|
|
21344
21695
|
computeCharPositions: () => computeCharPositions,
|
|
21696
|
+
computeFlowLines: () => computeFlowLines,
|
|
21345
21697
|
computeLineBreaks: () => computeLineBreaks,
|
|
21346
21698
|
computeTotalHeight: () => computeTotalHeight,
|
|
21699
|
+
layoutNextLine: () => layoutNextLine,
|
|
21347
21700
|
measureBlock: () => measureBlock,
|
|
21348
21701
|
measureBlocks: () => measureBlocks,
|
|
21349
21702
|
reactiveBlockLayout: () => reactiveBlockLayout,
|
|
21350
|
-
|
|
21703
|
+
reactiveFlowLayout: () => reactiveFlowLayout,
|
|
21704
|
+
reactiveLayout: () => reactiveLayout,
|
|
21705
|
+
rectIntervalForBand: () => rectIntervalForBand
|
|
21351
21706
|
});
|
|
21352
21707
|
|
|
21353
21708
|
// src/patterns/reactive-layout/measurement-adapters.ts
|
|
@@ -21815,6 +22170,185 @@ function reactiveBlockLayout(opts) {
|
|
|
21815
22170
|
};
|
|
21816
22171
|
}
|
|
21817
22172
|
|
|
22173
|
+
// src/patterns/reactive-layout/reactive-flow-layout.ts
|
|
22174
|
+
function circleIntervalForBand(o, bandTop, bandBottom) {
|
|
22175
|
+
const hPad = o.hPad ?? 0;
|
|
22176
|
+
const vPad = o.vPad ?? 0;
|
|
22177
|
+
const top = bandTop - vPad;
|
|
22178
|
+
const bottom = bandBottom + vPad;
|
|
22179
|
+
if (top >= o.cy + o.r || bottom <= o.cy - o.r) return null;
|
|
22180
|
+
const minDy = o.cy >= top && o.cy <= bottom ? 0 : o.cy < top ? top - o.cy : o.cy - bottom;
|
|
22181
|
+
if (minDy >= o.r) return null;
|
|
22182
|
+
const maxDx = Math.sqrt(o.r * o.r - minDy * minDy);
|
|
22183
|
+
return { left: o.cx - maxDx - hPad, right: o.cx + maxDx + hPad };
|
|
22184
|
+
}
|
|
22185
|
+
function rectIntervalForBand(o, bandTop, bandBottom) {
|
|
22186
|
+
const hPad = o.hPad ?? 0;
|
|
22187
|
+
const vPad = o.vPad ?? 0;
|
|
22188
|
+
if (bandBottom <= o.y - vPad) return null;
|
|
22189
|
+
if (bandTop >= o.y + o.h + vPad) return null;
|
|
22190
|
+
return { left: o.x - hPad, right: o.x + o.w + hPad };
|
|
22191
|
+
}
|
|
22192
|
+
function obstacleIntervalForBand(o, bandTop, bandBottom) {
|
|
22193
|
+
return o.kind === "circle" ? circleIntervalForBand(o, bandTop, bandBottom) : rectIntervalForBand(o, bandTop, bandBottom);
|
|
22194
|
+
}
|
|
22195
|
+
function computeFlowLines(segments, container, columns, obstacles, lineHeight, minSlotWidth) {
|
|
22196
|
+
const lines = [];
|
|
22197
|
+
let cursor = { segmentIndex: 0, graphemeIndex: 0 };
|
|
22198
|
+
if (segments.length === 0 || columns.count <= 0 || lineHeight <= 0) {
|
|
22199
|
+
return { lines, cursor };
|
|
22200
|
+
}
|
|
22201
|
+
const padX = container.paddingX ?? 0;
|
|
22202
|
+
const padY = container.paddingY ?? 0;
|
|
22203
|
+
const availWidth = Math.max(0, container.width - padX * 2);
|
|
22204
|
+
const availHeight = Math.max(0, container.height - padY * 2);
|
|
22205
|
+
const gapTotal = columns.gap * Math.max(0, columns.count - 1);
|
|
22206
|
+
const colWidth = Math.max(0, (availWidth - gapTotal) / columns.count);
|
|
22207
|
+
if (colWidth <= 0) return { lines, cursor };
|
|
22208
|
+
outerCol: for (let col = 0; col < columns.count; col++) {
|
|
22209
|
+
const colLeft = padX + col * (colWidth + columns.gap);
|
|
22210
|
+
const colRight = colLeft + colWidth;
|
|
22211
|
+
let bandTop = padY;
|
|
22212
|
+
while (bandTop + lineHeight <= padY + availHeight) {
|
|
22213
|
+
const bandBottom = bandTop + lineHeight;
|
|
22214
|
+
const blocked = [];
|
|
22215
|
+
for (let oi = 0; oi < obstacles.length; oi++) {
|
|
22216
|
+
const iv = obstacleIntervalForBand(obstacles[oi], bandTop, bandBottom);
|
|
22217
|
+
if (iv !== null) blocked.push(iv);
|
|
22218
|
+
}
|
|
22219
|
+
const slots = carveTextLineSlots({ left: colLeft, right: colRight }, blocked, minSlotWidth);
|
|
22220
|
+
if (slots.length === 0) {
|
|
22221
|
+
bandTop += lineHeight;
|
|
22222
|
+
continue;
|
|
22223
|
+
}
|
|
22224
|
+
let hardBreakThisBand = false;
|
|
22225
|
+
for (let si = 0; si < slots.length; si++) {
|
|
22226
|
+
const slot = slots[si];
|
|
22227
|
+
const slotW = slot.right - slot.left;
|
|
22228
|
+
const line = layoutNextLine(segments, cursor, slotW);
|
|
22229
|
+
if (line === null) {
|
|
22230
|
+
return { lines, cursor };
|
|
22231
|
+
}
|
|
22232
|
+
if (line.text.length === 0 && line.width === 0) {
|
|
22233
|
+
cursor = line.end;
|
|
22234
|
+
hardBreakThisBand = true;
|
|
22235
|
+
break;
|
|
22236
|
+
}
|
|
22237
|
+
lines.push({
|
|
22238
|
+
x: slot.left,
|
|
22239
|
+
y: bandTop,
|
|
22240
|
+
width: line.width,
|
|
22241
|
+
slotWidth: slotW,
|
|
22242
|
+
text: line.text,
|
|
22243
|
+
columnIndex: col,
|
|
22244
|
+
flushToRight: slot.right < colRight - 0.5
|
|
22245
|
+
});
|
|
22246
|
+
cursor = line.end;
|
|
22247
|
+
}
|
|
22248
|
+
bandTop += lineHeight;
|
|
22249
|
+
if (hardBreakThisBand) continue;
|
|
22250
|
+
if (cursor.segmentIndex >= segments.length) break outerCol;
|
|
22251
|
+
}
|
|
22252
|
+
if (cursor.segmentIndex >= segments.length) break;
|
|
22253
|
+
}
|
|
22254
|
+
return { lines, cursor };
|
|
22255
|
+
}
|
|
22256
|
+
function reactiveFlowLayout(opts) {
|
|
22257
|
+
const { adapter, name = "reactive-flow-layout", minSlotWidth = 20 } = opts;
|
|
22258
|
+
const g = new Graph(name);
|
|
22259
|
+
const measureCache = /* @__PURE__ */ new Map();
|
|
22260
|
+
const textNode = state(opts.text ?? "", { name: "text" });
|
|
22261
|
+
const fontNode = state(opts.font ?? "16px sans-serif", { name: "font" });
|
|
22262
|
+
const lineHeightNode = state(opts.lineHeight ?? 20, { name: "line-height" });
|
|
22263
|
+
const containerNode = state(
|
|
22264
|
+
opts.container ?? { width: 800, height: 600, paddingX: 0, paddingY: 0 },
|
|
22265
|
+
{ name: "container" }
|
|
22266
|
+
);
|
|
22267
|
+
const columnsNode = state(opts.columns ?? { count: 1, gap: 0 }, {
|
|
22268
|
+
name: "columns"
|
|
22269
|
+
});
|
|
22270
|
+
const obstaclesNode = state(opts.obstacles ?? [], { name: "obstacles" });
|
|
22271
|
+
const segmentsNode = node(
|
|
22272
|
+
[textNode, fontNode],
|
|
22273
|
+
(data, actions, ctx) => {
|
|
22274
|
+
const b0 = data[0];
|
|
22275
|
+
const textVal = b0 != null && b0.length > 0 ? b0.at(-1) : ctx.prevData[0];
|
|
22276
|
+
const b1 = data[1];
|
|
22277
|
+
const fontVal = b1 != null && b1.length > 0 ? b1.at(-1) : ctx.prevData[1];
|
|
22278
|
+
const result = analyzeAndMeasure(textVal, fontVal, adapter, measureCache);
|
|
22279
|
+
actions.emit(result);
|
|
22280
|
+
return () => {
|
|
22281
|
+
measureCache.clear();
|
|
22282
|
+
adapter.clearCache?.();
|
|
22283
|
+
};
|
|
22284
|
+
},
|
|
22285
|
+
{ name: "segments", describeKind: "derived" }
|
|
22286
|
+
);
|
|
22287
|
+
const flowLinesNode = derived(
|
|
22288
|
+
[segmentsNode, containerNode, columnsNode, obstaclesNode, lineHeightNode],
|
|
22289
|
+
([segs, cont, cols, obs, lh]) => {
|
|
22290
|
+
const segments = segs;
|
|
22291
|
+
const t0 = monotonicNs();
|
|
22292
|
+
const { lines: result, cursor } = computeFlowLines(
|
|
22293
|
+
segments,
|
|
22294
|
+
cont,
|
|
22295
|
+
cols,
|
|
22296
|
+
obs,
|
|
22297
|
+
lh,
|
|
22298
|
+
minSlotWidth
|
|
22299
|
+
);
|
|
22300
|
+
const elapsed = monotonicNs() - t0;
|
|
22301
|
+
const overflow = Math.max(0, segments.length - cursor.segmentIndex);
|
|
22302
|
+
const meta = flowLinesNode.meta;
|
|
22303
|
+
if (meta) {
|
|
22304
|
+
emitToMeta(meta["line-count"], result.length);
|
|
22305
|
+
emitToMeta(meta["layout-time-ns"], elapsed);
|
|
22306
|
+
emitToMeta(meta["overflow-segments"], overflow);
|
|
22307
|
+
}
|
|
22308
|
+
return result;
|
|
22309
|
+
},
|
|
22310
|
+
{
|
|
22311
|
+
name: "flow-lines",
|
|
22312
|
+
meta: {
|
|
22313
|
+
"line-count": 0,
|
|
22314
|
+
"layout-time-ns": 0,
|
|
22315
|
+
"overflow-segments": 0
|
|
22316
|
+
},
|
|
22317
|
+
equals: (a, b) => {
|
|
22318
|
+
const la = a;
|
|
22319
|
+
const lb = b;
|
|
22320
|
+
if (la.length !== lb.length) return false;
|
|
22321
|
+
for (let i = 0; i < la.length; i++) {
|
|
22322
|
+
const pa = la[i];
|
|
22323
|
+
const pb = lb[i];
|
|
22324
|
+
if (pa.x !== pb.x || pa.y !== pb.y || pa.width !== pb.width || pa.slotWidth !== pb.slotWidth || pa.text !== pb.text || pa.columnIndex !== pb.columnIndex || pa.flushToRight !== pb.flushToRight)
|
|
22325
|
+
return false;
|
|
22326
|
+
}
|
|
22327
|
+
return true;
|
|
22328
|
+
}
|
|
22329
|
+
}
|
|
22330
|
+
);
|
|
22331
|
+
g.add("text", textNode);
|
|
22332
|
+
g.add("font", fontNode);
|
|
22333
|
+
g.add("line-height", lineHeightNode);
|
|
22334
|
+
g.add("container", containerNode);
|
|
22335
|
+
g.add("columns", columnsNode);
|
|
22336
|
+
g.add("obstacles", obstaclesNode);
|
|
22337
|
+
g.add("segments", segmentsNode);
|
|
22338
|
+
g.add("flow-lines", flowLinesNode);
|
|
22339
|
+
return {
|
|
22340
|
+
graph: g,
|
|
22341
|
+
setText: (t) => g.set("text", t),
|
|
22342
|
+
setFont: (f) => g.set("font", f),
|
|
22343
|
+
setLineHeight: (lh) => g.set("line-height", lh),
|
|
22344
|
+
setContainer: (c) => g.set("container", c),
|
|
22345
|
+
setColumns: (c) => g.set("columns", c),
|
|
22346
|
+
setObstacles: (o) => g.set("obstacles", o),
|
|
22347
|
+
segments: segmentsNode,
|
|
22348
|
+
flowLines: flowLinesNode
|
|
22349
|
+
};
|
|
22350
|
+
}
|
|
22351
|
+
|
|
21818
22352
|
// src/index.ts
|
|
21819
22353
|
var version = "0.0.0";
|
|
21820
22354
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -21954,6 +22488,7 @@ var version = "0.0.0";
|
|
|
21954
22488
|
fromPromise,
|
|
21955
22489
|
fromPulsar,
|
|
21956
22490
|
fromRabbitMQ,
|
|
22491
|
+
fromRaf,
|
|
21957
22492
|
fromRedisStream,
|
|
21958
22493
|
fromSSE,
|
|
21959
22494
|
fromSqlite,
|