@graphrefly/graphrefly 0.23.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-NZMBRXQV.js → chunk-5DJTTKX3.js} +11 -13
- package/dist/chunk-5DJTTKX3.js.map +1 -0
- package/dist/{chunk-PNUZM7PC.js → chunk-EVR6UFUV.js} +6 -6
- package/dist/{chunk-HVBX5KIW.js → chunk-H4RVA4VE.js} +2 -2
- package/dist/{chunk-32N5A454.js → chunk-HWPIFSW2.js} +2 -2
- package/dist/chunk-HWPIFSW2.js.map +1 -0
- package/dist/{chunk-XTLYW4FR.js → chunk-IAHGTNOZ.js} +6 -4
- package/dist/{chunk-XTLYW4FR.js.map → chunk-IAHGTNOZ.js.map} +1 -1
- package/dist/{chunk-CWYPA63G.js → chunk-L2GLW2U7.js} +69 -2
- package/dist/chunk-L2GLW2U7.js.map +1 -0
- package/dist/{chunk-2GQLMQVJ.js → chunk-MW4VAKAO.js} +3 -3
- package/dist/{chunk-JFONSPNF.js → chunk-PY4XCDLR.js} +2 -2
- package/dist/{chunk-263BEJJO.js → chunk-QOWVNWOC.js} +3 -3
- package/dist/{chunk-PX6PDUJ5.js → chunk-TKE3JGOH.js} +491 -19
- package/dist/chunk-TKE3JGOH.js.map +1 -0
- package/dist/{chunk-XRFJJ2IU.js → chunk-XOFWRC73.js} +3 -3
- package/dist/compat/nestjs/index.cjs +10 -12
- package/dist/compat/nestjs/index.cjs.map +1 -1
- package/dist/compat/nestjs/index.d.cts +6 -6
- package/dist/compat/nestjs/index.d.ts +6 -6
- package/dist/compat/nestjs/index.js +9 -9
- package/dist/core/index.cjs +10 -12
- package/dist/core/index.cjs.map +1 -1
- package/dist/core/index.d.cts +3 -3
- package/dist/core/index.d.ts +3 -3
- package/dist/core/index.js +3 -3
- package/dist/extra/index.cjs +78 -12
- package/dist/extra/index.cjs.map +1 -1
- package/dist/extra/index.d.cts +4 -4
- package/dist/extra/index.d.ts +4 -4
- package/dist/extra/index.js +6 -4
- package/dist/graph/index.cjs +10 -12
- package/dist/graph/index.cjs.map +1 -1
- package/dist/graph/index.d.cts +5 -5
- package/dist/graph/index.d.ts +5 -5
- package/dist/graph/index.js +4 -4
- package/dist/{graph-CEO2FkLY.d.ts → graph-B6NFqv3z.d.ts} +3 -3
- package/dist/{graph-BtdSRHUc.d.cts → graph-D-3JIQme.d.cts} +3 -3
- package/dist/{index-BFGjXbiP.d.cts → index-AMWewNDe.d.cts} +2 -2
- package/dist/{index-BUj3ASVe.d.cts → index-BJB7t9gg.d.cts} +10 -24
- package/dist/{index-DSPc5rkv.d.ts → index-C-TXEa7C.d.ts} +10 -24
- package/dist/{index-CkElcUY6.d.ts → index-CYkjxu3s.d.ts} +2 -2
- package/dist/{index-B0tfuXwV.d.cts → index-Ch0IpIO0.d.cts} +32 -5
- package/dist/{index-C59uSJAH.d.cts → index-DKE1EATr.d.cts} +224 -4
- package/dist/{index-DgscL7v0.d.ts → index-DiobMNwE.d.ts} +3 -3
- package/dist/{index-RXN94sHK.d.ts → index-Ds23Wvou.d.ts} +32 -5
- package/dist/{index-BPlWVAKY.d.cts → index-J7Kc0oIQ.d.cts} +3 -3
- package/dist/{index-jEtF4N7L.d.ts → index-OXImXMq6.d.ts} +224 -4
- package/dist/index.cjs +570 -47
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -15
- package/dist/index.d.ts +15 -15
- package/dist/index.js +23 -31
- package/dist/index.js.map +1 -1
- package/dist/{meta-3QjzotRv.d.ts → meta-CnkLA_43.d.ts} +1 -1
- package/dist/{meta-B-Lbs4-O.d.cts → meta-DWbkoq1s.d.cts} +1 -1
- package/dist/{node-C7PD3sn9.d.cts → node-B-f-Lu-k.d.cts} +15 -13
- package/dist/{node-C7PD3sn9.d.ts → node-B-f-Lu-k.d.ts} +15 -13
- package/dist/{observable-axpzv1K2.d.cts → observable-DBnrwcar.d.cts} +1 -1
- package/dist/{observable-EyO-moQY.d.ts → observable-uP-wy_uK.d.ts} +1 -1
- package/dist/patterns/reactive-layout/index.cjs +498 -28
- package/dist/patterns/reactive-layout/index.cjs.map +1 -1
- package/dist/patterns/reactive-layout/index.d.cts +5 -5
- package/dist/patterns/reactive-layout/index.d.ts +5 -5
- package/dist/patterns/reactive-layout/index.js +20 -8
- package/dist/{storage-DIgAr7M_.d.cts → storage-BuTdpCI1.d.cts} +1 -1
- package/dist/{storage-CHT5WE9m.d.ts → storage-F2X1U1x0.d.ts} +1 -1
- package/package.json +2 -2
- package/dist/chunk-32N5A454.js.map +0 -1
- package/dist/chunk-CWYPA63G.js.map +0 -1
- package/dist/chunk-NZMBRXQV.js.map +0 -1
- package/dist/chunk-PX6PDUJ5.js.map +0 -1
- /package/dist/{chunk-PNUZM7PC.js.map → chunk-EVR6UFUV.js.map} +0 -0
- /package/dist/{chunk-HVBX5KIW.js.map → chunk-H4RVA4VE.js.map} +0 -0
- /package/dist/{chunk-2GQLMQVJ.js.map → chunk-MW4VAKAO.js.map} +0 -0
- /package/dist/{chunk-JFONSPNF.js.map → chunk-PY4XCDLR.js.map} +0 -0
- /package/dist/{chunk-263BEJJO.js.map → chunk-QOWVNWOC.js.map} +0 -0
- /package/dist/{chunk-XRFJJ2IU.js.map → chunk-XOFWRC73.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,
|
|
@@ -2132,37 +2133,35 @@ var NodeImpl = class _NodeImpl {
|
|
|
2132
2133
|
// --- Emit pipeline ---
|
|
2133
2134
|
/**
|
|
2134
2135
|
* @internal The unified dispatch waist — one call = one wave.
|
|
2136
|
+
* See `GRAPHREFLY-SPEC.md` §1.3.1 for protocol context — the stages
|
|
2137
|
+
* below are the implementation order.
|
|
2135
2138
|
*
|
|
2136
2139
|
* Pipeline stages, in order:
|
|
2137
2140
|
*
|
|
2138
|
-
* 1.
|
|
2139
|
-
* 2. Terminal filter — post-COMPLETE/ERROR only TEARDOWN/INVALIDATE
|
|
2141
|
+
* 1. Terminal filter — post-COMPLETE/ERROR only TEARDOWN/INVALIDATE
|
|
2140
2142
|
* still propagate so graph teardown and cache-clear still work.
|
|
2141
|
-
*
|
|
2143
|
+
* 2. Tier sort (stable) — the batch can be in any order when it
|
|
2142
2144
|
* arrives; the walker downstream (`downWithBatch`) assumes
|
|
2143
2145
|
* ascending tier monotone, and so does `_updateState`'s tier-3
|
|
2144
2146
|
* slice walk. This is the single source of truth for ordering.
|
|
2145
|
-
*
|
|
2147
|
+
* 3. Synthetic DIRTY prefix — if a tier-3 payload is present, no
|
|
2146
2148
|
* DIRTY is already in the batch, and the node isn't already in
|
|
2147
2149
|
* `"dirty"` status, prepend `[DIRTY]` after any tier-0 START
|
|
2148
2150
|
* entries. Guarantees spec §1.3.1 (DIRTY precedes DATA within
|
|
2149
2151
|
* the same batch) uniformly across every entry point.
|
|
2150
|
-
*
|
|
2152
|
+
* 4. PAUSE/RESUME lock bookkeeping (C0) — update `_pauseLocks`,
|
|
2151
2153
|
* derive `_paused`, filter unknown-lockId RESUME, replay
|
|
2152
2154
|
* bufferAll buffer on final lock release.
|
|
2153
|
-
*
|
|
2155
|
+
* 5. Meta TEARDOWN fan-out — notify meta children before
|
|
2154
2156
|
* `_updateState`'s TEARDOWN branch calls `_deactivate`. Hoisted
|
|
2155
2157
|
* out of the walk to keep `_updateState` re-entrance-free.
|
|
2156
|
-
*
|
|
2158
|
+
* 6. `_updateState` — walk the batch in tier order, advancing
|
|
2157
2159
|
* `_cached` / `_status` / `_versioning` and running equals
|
|
2158
2160
|
* substitution on tier-3 DATA (§3.5.1). Returns
|
|
2159
2161
|
* `{finalMessages, equalsError?}`.
|
|
2160
|
-
*
|
|
2162
|
+
* 7. `downWithBatch` dispatch (or bufferAll capture if paused with
|
|
2161
2163
|
* `pausable: "resumeAll"`).
|
|
2162
|
-
*
|
|
2163
|
-
*
|
|
2164
|
-
* `node.down` / `node.emit` / `actions.down` / `actions.emit` all
|
|
2165
|
-
* converge here — the unified `_emit` waist (spec §1.3.1).
|
|
2164
|
+
* 8. Recursive ERROR emission if equals threw mid-walk.
|
|
2166
2165
|
*/
|
|
2167
2166
|
_emit(messages) {
|
|
2168
2167
|
if (messages.length === 0) return;
|
|
@@ -3188,6 +3187,72 @@ function fromTimer(ms, opts) {
|
|
|
3188
3187
|
return cleanup;
|
|
3189
3188
|
}, sourceOpts(rest));
|
|
3190
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
|
+
}
|
|
3191
3256
|
function fromCron(expr, opts) {
|
|
3192
3257
|
const schedule = parseCron(expr);
|
|
3193
3258
|
const { tickMs: tickOpt, output, ...rest } = opts ?? {};
|
|
@@ -8187,20 +8252,12 @@ function useStore4(node2) {
|
|
|
8187
8252
|
function useSubscribeRecord4(keys, factory) {
|
|
8188
8253
|
const result = (0, import_vue.shallowRef)({});
|
|
8189
8254
|
const activeSubs = /* @__PURE__ */ new Map();
|
|
8190
|
-
|
|
8191
|
-
|
|
8192
|
-
|
|
8193
|
-
|
|
8194
|
-
|
|
8195
|
-
|
|
8196
|
-
if (disposed) return;
|
|
8197
|
-
batchPending = false;
|
|
8198
|
-
const snap = {};
|
|
8199
|
-
for (const [key, entry] of activeSubs) {
|
|
8200
|
-
snap[key] = { ...entry.values };
|
|
8201
|
-
}
|
|
8202
|
-
result.value = snap;
|
|
8203
|
-
});
|
|
8255
|
+
function flushResult() {
|
|
8256
|
+
const snap = {};
|
|
8257
|
+
for (const [key, entry] of activeSubs) {
|
|
8258
|
+
snap[key] = { ...entry.values };
|
|
8259
|
+
}
|
|
8260
|
+
result.value = snap;
|
|
8204
8261
|
}
|
|
8205
8262
|
function sync(newKeys) {
|
|
8206
8263
|
for (const entry of activeSubs.values()) {
|
|
@@ -8217,7 +8274,7 @@ function useSubscribeRecord4(keys, factory) {
|
|
|
8217
8274
|
values[field] = node2.cache;
|
|
8218
8275
|
const unsub = node2.subscribe(() => {
|
|
8219
8276
|
values[field] = node2.cache;
|
|
8220
|
-
|
|
8277
|
+
flushResult();
|
|
8221
8278
|
});
|
|
8222
8279
|
subs.push(unsub);
|
|
8223
8280
|
}
|
|
@@ -8236,7 +8293,6 @@ function useSubscribeRecord4(keys, factory) {
|
|
|
8236
8293
|
(0, import_vue.watch)(readKeys, (newKeys) => sync(newKeys ?? []), { immediate: true });
|
|
8237
8294
|
if ((0, import_vue.getCurrentScope)()) {
|
|
8238
8295
|
(0, import_vue.onScopeDispose)(() => {
|
|
8239
|
-
disposed = true;
|
|
8240
8296
|
for (const entry of activeSubs.values()) {
|
|
8241
8297
|
for (const unsub of entry.subs) unsub();
|
|
8242
8298
|
}
|
|
@@ -8265,18 +8321,17 @@ function create(initializer) {
|
|
|
8265
8321
|
g.add("state", s);
|
|
8266
8322
|
const getState = () => s.cache;
|
|
8267
8323
|
const setState = (partial, replace) => {
|
|
8268
|
-
const prev =
|
|
8324
|
+
const prev = s.cache;
|
|
8269
8325
|
const next = typeof partial === "function" ? partial(prev) : partial;
|
|
8270
|
-
|
|
8271
|
-
s.emit(nextState);
|
|
8326
|
+
s.emit(replace ? next : { ...prev, ...next });
|
|
8272
8327
|
};
|
|
8273
8328
|
const api = {
|
|
8274
8329
|
getState,
|
|
8275
8330
|
setState,
|
|
8276
8331
|
getInitialState: () => initialValue,
|
|
8277
8332
|
subscribe: (listener) => {
|
|
8278
|
-
let prev = getState();
|
|
8279
8333
|
let initial = true;
|
|
8334
|
+
let prev = s.cache;
|
|
8280
8335
|
return s.subscribe((msgs) => {
|
|
8281
8336
|
for (const [t, v] of msgs) {
|
|
8282
8337
|
if (t === DATA) {
|
|
@@ -8380,6 +8435,7 @@ __export(extra_exports, {
|
|
|
8380
8435
|
fromPromise: () => fromPromise,
|
|
8381
8436
|
fromPulsar: () => fromPulsar,
|
|
8382
8437
|
fromRabbitMQ: () => fromRabbitMQ,
|
|
8438
|
+
fromRaf: () => fromRaf,
|
|
8383
8439
|
fromRedisStream: () => fromRedisStream,
|
|
8384
8440
|
fromSSE: () => fromSSE,
|
|
8385
8441
|
fromSqlite: () => fromSqlite,
|
|
@@ -18066,7 +18122,7 @@ function analyzeAndMeasure(text, font, adapter, cache, stats) {
|
|
|
18066
18122
|
const normalized = normalizeWhitespace(text);
|
|
18067
18123
|
if (normalized.length === 0) return [];
|
|
18068
18124
|
const pieces = segmentText(normalized);
|
|
18069
|
-
const
|
|
18125
|
+
const graphemeSegmenter2 = new Intl.Segmenter(void 0, {
|
|
18070
18126
|
granularity: "grapheme"
|
|
18071
18127
|
});
|
|
18072
18128
|
const rawTexts = [];
|
|
@@ -18110,7 +18166,8 @@ function analyzeAndMeasure(text, font, adapter, cache, stats) {
|
|
|
18110
18166
|
let w = fontCache.get(seg);
|
|
18111
18167
|
if (w === void 0) {
|
|
18112
18168
|
if (stats) stats.misses += 1;
|
|
18113
|
-
|
|
18169
|
+
const raw = adapter.measureSegment(seg, font).width;
|
|
18170
|
+
w = Number.isFinite(raw) && raw >= 0 ? raw : 0;
|
|
18114
18171
|
fontCache.set(seg, w);
|
|
18115
18172
|
} else if (stats) {
|
|
18116
18173
|
stats.hits += 1;
|
|
@@ -18132,7 +18189,7 @@ function analyzeAndMeasure(text, font, adapter, cache, stats) {
|
|
|
18132
18189
|
}
|
|
18133
18190
|
if (isCJK(t)) {
|
|
18134
18191
|
let unitText = "";
|
|
18135
|
-
for (const gs of
|
|
18192
|
+
for (const gs of graphemeSegmenter2.segment(t)) {
|
|
18136
18193
|
const grapheme = gs.segment;
|
|
18137
18194
|
if (unitText.length > 0 && kinsokuStart.has(grapheme)) {
|
|
18138
18195
|
unitText += grapheme;
|
|
@@ -18164,7 +18221,7 @@ function analyzeAndMeasure(text, font, adapter, cache, stats) {
|
|
|
18164
18221
|
let graphemeWidths = null;
|
|
18165
18222
|
if (mergedWordLike[i] && t.length > 1) {
|
|
18166
18223
|
const gWidths = [];
|
|
18167
|
-
for (const gs of
|
|
18224
|
+
for (const gs of graphemeSegmenter2.segment(t)) {
|
|
18168
18225
|
gWidths.push(measureCached(gs.segment));
|
|
18169
18226
|
}
|
|
18170
18227
|
if (gWidths.length > 1) {
|
|
@@ -18204,10 +18261,10 @@ function computeLineBreaks(segments, maxWidth, adapter, font, cache) {
|
|
|
18204
18261
|
const seg = segments[i];
|
|
18205
18262
|
if (seg.kind === "soft-hyphen" || seg.kind === "hard-break") continue;
|
|
18206
18263
|
if (i === lineStartSeg && lineStartGrapheme > 0 && seg.graphemeWidths) {
|
|
18207
|
-
const
|
|
18264
|
+
const graphemeSegmenter2 = new Intl.Segmenter(void 0, {
|
|
18208
18265
|
granularity: "grapheme"
|
|
18209
18266
|
});
|
|
18210
|
-
const graphemes = [...
|
|
18267
|
+
const graphemes = [...graphemeSegmenter2.segment(seg.text)].map((g) => g.segment);
|
|
18211
18268
|
text += graphemes.slice(lineStartGrapheme).join("");
|
|
18212
18269
|
} else {
|
|
18213
18270
|
text += seg.text;
|
|
@@ -18215,10 +18272,10 @@ function computeLineBreaks(segments, maxWidth, adapter, font, cache) {
|
|
|
18215
18272
|
}
|
|
18216
18273
|
if (endGrapheme > 0 && endSeg < segments.length) {
|
|
18217
18274
|
const seg = segments[endSeg];
|
|
18218
|
-
const
|
|
18275
|
+
const graphemeSegmenter2 = new Intl.Segmenter(void 0, {
|
|
18219
18276
|
granularity: "grapheme"
|
|
18220
18277
|
});
|
|
18221
|
-
const graphemes = [...
|
|
18278
|
+
const graphemes = [...graphemeSegmenter2.segment(seg.text)].map((g) => g.segment);
|
|
18222
18279
|
const startG = lineStartSeg === endSeg ? lineStartGrapheme : 0;
|
|
18223
18280
|
text += graphemes.slice(startG, endGrapheme).join("");
|
|
18224
18281
|
}
|
|
@@ -18238,7 +18295,7 @@ function computeLineBreaks(segments, maxWidth, adapter, font, cache) {
|
|
|
18238
18295
|
pendingBreakSeg = -1;
|
|
18239
18296
|
pendingBreakWidth = 0;
|
|
18240
18297
|
}
|
|
18241
|
-
function
|
|
18298
|
+
function canBreakAfter2(kind) {
|
|
18242
18299
|
return kind === "space" || kind === "zero-width-break" || kind === "soft-hyphen";
|
|
18243
18300
|
}
|
|
18244
18301
|
function startLine(segIdx, graphemeIdx, width) {
|
|
@@ -18283,7 +18340,7 @@ function computeLineBreaks(segments, maxWidth, adapter, font, cache) {
|
|
|
18283
18340
|
} else {
|
|
18284
18341
|
startLine(i, 0, w);
|
|
18285
18342
|
}
|
|
18286
|
-
if (
|
|
18343
|
+
if (canBreakAfter2(seg.kind)) {
|
|
18287
18344
|
pendingBreakSeg = i + 1;
|
|
18288
18345
|
pendingBreakWidth = seg.kind === "space" ? lineW - w : lineW;
|
|
18289
18346
|
}
|
|
@@ -18291,7 +18348,7 @@ function computeLineBreaks(segments, maxWidth, adapter, font, cache) {
|
|
|
18291
18348
|
}
|
|
18292
18349
|
const newW = lineW + w;
|
|
18293
18350
|
if (newW > maxWidth + 5e-3) {
|
|
18294
|
-
if (
|
|
18351
|
+
if (canBreakAfter2(seg.kind)) {
|
|
18295
18352
|
lineW += w;
|
|
18296
18353
|
lineEndSeg = i + 1;
|
|
18297
18354
|
lineEndGrapheme = 0;
|
|
@@ -18315,7 +18372,7 @@ function computeLineBreaks(segments, maxWidth, adapter, font, cache) {
|
|
|
18315
18372
|
lineW = newW;
|
|
18316
18373
|
lineEndSeg = i + 1;
|
|
18317
18374
|
lineEndGrapheme = 0;
|
|
18318
|
-
if (
|
|
18375
|
+
if (canBreakAfter2(seg.kind)) {
|
|
18319
18376
|
pendingBreakSeg = i + 1;
|
|
18320
18377
|
pendingBreakWidth = seg.kind === "space" ? lineW - w : lineW;
|
|
18321
18378
|
}
|
|
@@ -18346,9 +18403,289 @@ function computeLineBreaks(segments, maxWidth, adapter, font, cache) {
|
|
|
18346
18403
|
}
|
|
18347
18404
|
}
|
|
18348
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
|
+
}
|
|
18349
18686
|
function computeCharPositions(lineBreaks, segments, lineHeight) {
|
|
18350
18687
|
const positions = [];
|
|
18351
|
-
const
|
|
18688
|
+
const graphemeSegmenter2 = new Intl.Segmenter(void 0, {
|
|
18352
18689
|
granularity: "grapheme"
|
|
18353
18690
|
});
|
|
18354
18691
|
for (let lineIdx = 0; lineIdx < lineBreaks.lines.length; lineIdx++) {
|
|
@@ -18361,7 +18698,7 @@ function computeCharPositions(lineBreaks, segments, lineHeight) {
|
|
|
18361
18698
|
if (si >= line.endSegment && line.endGrapheme === 0) break;
|
|
18362
18699
|
continue;
|
|
18363
18700
|
}
|
|
18364
|
-
const graphemes = [...
|
|
18701
|
+
const graphemes = [...graphemeSegmenter2.segment(seg.text)].map((g) => g.segment);
|
|
18365
18702
|
if (graphemes.length === 0) continue;
|
|
18366
18703
|
const startG = si === line.startSegment ? line.startGrapheme : 0;
|
|
18367
18704
|
let endG;
|
|
@@ -21352,14 +21689,20 @@ __export(reactive_layout_exports, {
|
|
|
21352
21689
|
PrecomputedAdapter: () => PrecomputedAdapter,
|
|
21353
21690
|
SvgBoundsAdapter: () => SvgBoundsAdapter,
|
|
21354
21691
|
analyzeAndMeasure: () => analyzeAndMeasure,
|
|
21692
|
+
carveTextLineSlots: () => carveTextLineSlots,
|
|
21693
|
+
circleIntervalForBand: () => circleIntervalForBand,
|
|
21355
21694
|
computeBlockFlow: () => computeBlockFlow,
|
|
21356
21695
|
computeCharPositions: () => computeCharPositions,
|
|
21696
|
+
computeFlowLines: () => computeFlowLines,
|
|
21357
21697
|
computeLineBreaks: () => computeLineBreaks,
|
|
21358
21698
|
computeTotalHeight: () => computeTotalHeight,
|
|
21699
|
+
layoutNextLine: () => layoutNextLine,
|
|
21359
21700
|
measureBlock: () => measureBlock,
|
|
21360
21701
|
measureBlocks: () => measureBlocks,
|
|
21361
21702
|
reactiveBlockLayout: () => reactiveBlockLayout,
|
|
21362
|
-
|
|
21703
|
+
reactiveFlowLayout: () => reactiveFlowLayout,
|
|
21704
|
+
reactiveLayout: () => reactiveLayout,
|
|
21705
|
+
rectIntervalForBand: () => rectIntervalForBand
|
|
21363
21706
|
});
|
|
21364
21707
|
|
|
21365
21708
|
// src/patterns/reactive-layout/measurement-adapters.ts
|
|
@@ -21827,6 +22170,185 @@ function reactiveBlockLayout(opts) {
|
|
|
21827
22170
|
};
|
|
21828
22171
|
}
|
|
21829
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
|
+
|
|
21830
22352
|
// src/index.ts
|
|
21831
22353
|
var version = "0.0.0";
|
|
21832
22354
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -21966,6 +22488,7 @@ var version = "0.0.0";
|
|
|
21966
22488
|
fromPromise,
|
|
21967
22489
|
fromPulsar,
|
|
21968
22490
|
fromRabbitMQ,
|
|
22491
|
+
fromRaf,
|
|
21969
22492
|
fromRedisStream,
|
|
21970
22493
|
fromSSE,
|
|
21971
22494
|
fromSqlite,
|