@opentrace/components 0.1.1-rc.66 → 0.1.1-rc.78

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.
@@ -496,6 +496,88 @@
496
496
  background: color-mix(in oklch, #f87171 12%, transparent);
497
497
  }
498
498
 
499
+ /* ── Import Picker ─────────────────────────── */
500
+ .import-picker {
501
+ display: flex;
502
+ flex-direction: column;
503
+ gap: 10px;
504
+ }
505
+
506
+ .import-dropzone {
507
+ display: flex;
508
+ flex-direction: column;
509
+ align-items: center;
510
+ justify-content: center;
511
+ gap: 8px;
512
+ padding: 28px 18px;
513
+ border: 2px dashed color-mix(in oklch, var(--border) 40%, transparent);
514
+ border-radius: 14px;
515
+ background: color-mix(in oklch, var(--foreground) 3%, transparent);
516
+ cursor: pointer;
517
+ transition:
518
+ border-color 0.15s,
519
+ background 0.15s;
520
+ }
521
+
522
+ .import-dropzone:hover {
523
+ border-color: color-mix(in oklch, var(--primary) 50%, transparent);
524
+ background: color-mix(in oklch, var(--primary) 5%, transparent);
525
+ }
526
+
527
+ .import-dropzone--active {
528
+ border-color: var(--primary);
529
+ background: color-mix(in oklch, var(--primary) 10%, transparent);
530
+ }
531
+
532
+ .import-dropzone--has-file {
533
+ flex-direction: row;
534
+ padding: 14px 18px;
535
+ border-style: solid;
536
+ border-color: color-mix(in oklch, var(--primary) 30%, transparent);
537
+ background: color-mix(in oklch, var(--primary) 5%, transparent);
538
+ }
539
+
540
+ .import-dropzone-icon {
541
+ color: var(--muted-foreground);
542
+ opacity: 0.5;
543
+ flex-shrink: 0;
544
+ }
545
+
546
+ .import-dropzone--has-file .import-dropzone-icon {
547
+ color: var(--primary);
548
+ opacity: 0.8;
549
+ }
550
+
551
+ .import-dropzone-label {
552
+ font-size: 0.82rem;
553
+ color: var(--muted-foreground);
554
+ }
555
+
556
+ .import-dropzone-filename {
557
+ font-size: 0.85rem;
558
+ font-weight: 500;
559
+ color: var(--foreground);
560
+ flex: 1;
561
+ min-width: 0;
562
+ overflow: hidden;
563
+ text-overflow: ellipsis;
564
+ white-space: nowrap;
565
+ }
566
+
567
+ .import-dropzone-size {
568
+ font-size: 0.75rem;
569
+ color: var(--muted-foreground);
570
+ flex-shrink: 0;
571
+ }
572
+
573
+ .form-info-code {
574
+ font-family: monospace;
575
+ font-size: 0.7rem;
576
+ padding: 1px 5px;
577
+ background: color-mix(in oklch, var(--foreground) 8%, transparent);
578
+ border-radius: 4px;
579
+ }
580
+
499
581
  /* ── Directory Picker ───────────────────────── */
500
582
  .directory-picker {
501
583
  position: relative;
package/dist/indexing.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const urlNormalize = require("./urlNormalize-DL0SAEQS.cjs");
3
+ const urlNormalize = require("./urlNormalize-B2tPP0bB.cjs");
4
4
  exports.AddRepoModal = urlNormalize.AddRepoModal;
5
5
  exports.IndexingProgress = urlNormalize.IndexingProgress;
6
6
  exports.detectProvider = urlNormalize.detectProvider;
package/dist/indexing.js CHANGED
@@ -1,4 +1,4 @@
1
- import { A, I, d, n } from "./urlNormalize-KY4ngwCQ.js";
1
+ import { A, I, d, n } from "./urlNormalize-D4tuih2G.js";
2
2
  export {
3
3
  A as AddRepoModal,
4
4
  I as IndexingProgress,
@@ -3,7 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const t = require("react");
5
5
  const useHighlights = require("./useHighlights-zx7DM4V0.cjs");
6
- const urlNormalize = require("./urlNormalize-DL0SAEQS.cjs");
6
+ const urlNormalize = require("./urlNormalize-B2tPP0bB.cjs");
7
7
  var _documentCurrentScript = typeof document !== "undefined" ? document.currentScript : null;
8
8
  function _toPrimitive$1(t2, r) {
9
9
  if ("object" != typeof t2 || !t2) return t2;
@@ -7196,6 +7196,68 @@ function LayoutPipeline({
7196
7196
  }, [layoutReady, optimizeTick, layoutConfig, start, stop, sigma]);
7197
7197
  return null;
7198
7198
  }
7199
+ let cached$1 = null;
7200
+ function resolveLabelColor() {
7201
+ const root = document.documentElement;
7202
+ const key = `${root.dataset.theme ?? ""}_${root.dataset.mode ?? ""}`;
7203
+ if (cached$1 && cached$1.key === key) return cached$1.fg;
7204
+ const style = getComputedStyle(root);
7205
+ const fg = style.getPropertyValue("--foreground").trim() || "#e2e8f0";
7206
+ cached$1 = { fg, key };
7207
+ return fg;
7208
+ }
7209
+ let renderedBoxes = [];
7210
+ let hoverBoxes = [];
7211
+ function resetLabelGrid() {
7212
+ renderedBoxes = [];
7213
+ }
7214
+ function resetHoverGrid() {
7215
+ hoverBoxes = [];
7216
+ }
7217
+ function overlaps(boxes, x, y, w2, h2) {
7218
+ for (const box of boxes) {
7219
+ if (x < box.x + box.w && x + w2 > box.x && y < box.y + box.h && y + h2 > box.y) {
7220
+ return true;
7221
+ }
7222
+ }
7223
+ return false;
7224
+ }
7225
+ function overlapsExistingHover(x, y, w2, h2) {
7226
+ return overlaps(hoverBoxes, x, y, w2, h2);
7227
+ }
7228
+ function pushHoverBox(x, y, w2, h2) {
7229
+ hoverBoxes.push({ x, y, w: w2, h: h2 });
7230
+ }
7231
+ function drawNodeLabel(context, data, settings) {
7232
+ if (!data.label) return;
7233
+ const extras = data;
7234
+ if (extras.highlighted) return;
7235
+ const size = settings.labelSize;
7236
+ const font = settings.labelFont;
7237
+ const weight = settings.labelWeight;
7238
+ const fg = resolveLabelColor();
7239
+ context.font = `${weight} ${size}px ${font}`;
7240
+ const textWidth = context.measureText(data.label).width;
7241
+ const x = data.x + data.size + 3;
7242
+ const y = data.y + size / 3;
7243
+ const boxX = x - 1;
7244
+ const boxY = y - size;
7245
+ const boxW = textWidth + 2;
7246
+ const boxH = size + 4;
7247
+ if (overlaps(renderedBoxes, boxX, boxY, boxW, boxH)) {
7248
+ return;
7249
+ }
7250
+ renderedBoxes.push({ x: boxX, y: boxY, w: boxW, h: boxH });
7251
+ context.save();
7252
+ context.strokeStyle = "rgba(0,0,0,0.7)";
7253
+ context.lineWidth = 3;
7254
+ context.lineJoin = "round";
7255
+ context.strokeText(data.label, x, y);
7256
+ context.restore();
7257
+ context.font = `${weight} ${size}px ${font}`;
7258
+ context.fillStyle = fg;
7259
+ context.fillText(data.label, x, y);
7260
+ }
7199
7261
  let _hoveredNodeKey = null;
7200
7262
  function setHoveredNodeKey(key) {
7201
7263
  _hoveredNodeKey = key;
@@ -7214,15 +7276,73 @@ function resolveThemeColors() {
7214
7276
  };
7215
7277
  return cached;
7216
7278
  }
7279
+ let tooltipBuffer = [];
7280
+ let tooltipContext = null;
7281
+ let flushScheduled = false;
7282
+ function flushTooltips() {
7283
+ const ctx = tooltipContext;
7284
+ if (!ctx || tooltipBuffer.length === 0) return;
7285
+ const colors = resolveThemeColors();
7286
+ for (const cmd of tooltipBuffer) {
7287
+ const radius = 4;
7288
+ ctx.fillStyle = colors.bg;
7289
+ ctx.shadowOffsetX = 0;
7290
+ ctx.shadowOffsetY = 2;
7291
+ ctx.shadowBlur = 8;
7292
+ ctx.shadowColor = "rgba(0,0,0,0.5)";
7293
+ ctx.beginPath();
7294
+ ctx.roundRect(cmd.x, cmd.y, cmd.w, cmd.h, radius);
7295
+ ctx.fill();
7296
+ if (cmd.isHovered) {
7297
+ ctx.shadowBlur = 0;
7298
+ ctx.strokeStyle = cmd.color;
7299
+ ctx.lineWidth = 2;
7300
+ ctx.stroke();
7301
+ }
7302
+ ctx.shadowOffsetX = 0;
7303
+ ctx.shadowOffsetY = 0;
7304
+ ctx.shadowBlur = 0;
7305
+ const textX = cmd.x + 4;
7306
+ const centerY = cmd.y + cmd.h / 2;
7307
+ if (cmd.label) {
7308
+ ctx.fillStyle = colors.fg;
7309
+ ctx.font = `${cmd.weight} ${cmd.labelSize}px ${cmd.font}`;
7310
+ ctx.fillText(
7311
+ cmd.label,
7312
+ textX,
7313
+ centerY + (cmd.subtitle ? -cmd.lineHeight / 2 + cmd.labelSize * 0.35 : cmd.labelSize / 3)
7314
+ );
7315
+ }
7316
+ if (cmd.subtitle) {
7317
+ ctx.fillStyle = colors.muted;
7318
+ ctx.font = `${cmd.smallSize}px ${cmd.font}`;
7319
+ ctx.fillText(
7320
+ cmd.subtitle,
7321
+ textX,
7322
+ centerY + cmd.lineHeight / 2
7323
+ );
7324
+ }
7325
+ }
7326
+ tooltipBuffer = [];
7327
+ tooltipContext = null;
7328
+ }
7329
+ let lastHoverFrameTime = 0;
7217
7330
  function drawNodeHover(context, data, settings) {
7218
- const key = data.key;
7219
- if (key && _hoveredNodeKey !== null && key !== _hoveredNodeKey) return;
7331
+ const now = performance.now();
7332
+ if (now - lastHoverFrameTime > 8) {
7333
+ resetHoverGrid();
7334
+ tooltipBuffer = [];
7335
+ lastHoverFrameTime = now;
7336
+ }
7337
+ tooltipContext = context;
7338
+ const extras = data;
7339
+ const key = extras.key;
7340
+ const isActuallyHovered = key != null && _hoveredNodeKey != null && key === _hoveredNodeKey;
7341
+ const isSelected = extras.borderSize != null && extras.borderSize > 0;
7220
7342
  const size = settings.labelSize;
7221
7343
  const font = settings.labelFont;
7222
7344
  const weight = settings.labelWeight;
7223
- const colors = resolveThemeColors();
7224
7345
  const PADDING = 4;
7225
- const extras = data;
7226
7346
  const label = typeof data.label === "string" ? data.label : typeof extras._originalLabel === "string" ? extras._originalLabel : "";
7227
7347
  const nodeType = extras.nodeType;
7228
7348
  const communityName = extras._communityName;
@@ -7236,63 +7356,58 @@ function drawNodeHover(context, data, settings) {
7236
7356
  subtitleWidth = context.measureText(subtitle).width;
7237
7357
  }
7238
7358
  const textWidth = Math.max(labelWidth, subtitleWidth);
7239
- if (textWidth === 0 && !subtitle) {
7240
- context.beginPath();
7241
- context.arc(data.x, data.y, data.size + PADDING, 0, Math.PI * 2);
7242
- context.closePath();
7243
- context.fillStyle = colors.bg;
7244
- context.shadowBlur = 10;
7245
- context.shadowColor = "rgba(0,0,0,0.5)";
7246
- context.fill();
7247
- context.shadowBlur = 0;
7248
- context.beginPath();
7249
- context.arc(data.x, data.y, data.size, 0, Math.PI * 2);
7250
- context.closePath();
7251
- context.fillStyle = data.color;
7252
- context.fill();
7253
- return;
7254
- }
7255
7359
  const boxWidth = Math.round(textWidth + 8);
7256
7360
  const lineHeight = size + 2;
7257
7361
  const lines = subtitle ? 2 : 1;
7258
7362
  const boxHeight = Math.round(lineHeight * lines + PADDING * 2);
7259
- const nodeRadius = Math.max(data.size, size / 2) + PADDING;
7260
- const angleRadian = Math.asin(Math.min(1, boxHeight / 2 / nodeRadius));
7261
- const xDelta = Math.sqrt(
7262
- Math.abs(Math.pow(nodeRadius, 2) - Math.pow(boxHeight / 2, 2))
7263
- );
7264
- context.fillStyle = colors.bg;
7265
- context.shadowOffsetX = 0;
7266
- context.shadowOffsetY = 2;
7267
- context.shadowBlur = 10;
7268
- context.shadowColor = "rgba(0,0,0,0.5)";
7269
- context.beginPath();
7270
- context.moveTo(data.x + xDelta, data.y + boxHeight / 2);
7271
- context.lineTo(data.x + nodeRadius + boxWidth, data.y + boxHeight / 2);
7272
- context.lineTo(data.x + nodeRadius + boxWidth, data.y - boxHeight / 2);
7273
- context.lineTo(data.x + xDelta, data.y - boxHeight / 2);
7274
- context.arc(data.x, data.y, nodeRadius, angleRadian, -angleRadian);
7275
- context.closePath();
7276
- context.fill();
7277
- context.shadowOffsetX = 0;
7278
- context.shadowOffsetY = 0;
7279
- context.shadowBlur = 0;
7280
- const textX = data.x + nodeRadius + 4;
7281
- if (label) {
7282
- context.fillStyle = colors.fg;
7283
- context.font = `${weight} ${size}px ${font}`;
7284
- context.fillText(label, textX, data.y + (subtitle ? -1 : size / 3));
7285
- }
7286
- if (subtitle) {
7287
- context.fillStyle = colors.muted;
7288
- context.font = `${smallSize}px ${font}`;
7289
- context.fillText(subtitle, textX, data.y + lineHeight - 2);
7363
+ const tooltipGap = 4;
7364
+ const tx = data.x + data.size + tooltipGap;
7365
+ const ty = data.y - boxHeight / 2;
7366
+ const hasTooltip = textWidth > 0 || subtitle;
7367
+ let drawTooltip = hasTooltip;
7368
+ const pad = 8;
7369
+ const cullX = data.x - data.size - pad;
7370
+ const cullY = data.y - Math.max(boxHeight / 2, data.size) - pad;
7371
+ const cullW = data.size * 2 + boxWidth + tooltipGap + pad * 2;
7372
+ const cullH = Math.max(boxHeight, data.size * 2) + pad * 2;
7373
+ if (hasTooltip && !isActuallyHovered && !isSelected) {
7374
+ if (overlapsExistingHover(cullX, cullY, cullW, cullH)) {
7375
+ drawTooltip = false;
7376
+ } else {
7377
+ pushHoverBox(cullX, cullY, cullW, cullH);
7378
+ }
7379
+ } else if (hasTooltip) {
7380
+ pushHoverBox(cullX, cullY, cullW, cullH);
7290
7381
  }
7291
7382
  context.beginPath();
7292
7383
  context.arc(data.x, data.y, data.size, 0, Math.PI * 2);
7293
7384
  context.closePath();
7294
7385
  context.fillStyle = data.color;
7295
7386
  context.fill();
7387
+ if (drawTooltip) {
7388
+ tooltipBuffer.push({
7389
+ x: tx,
7390
+ y: ty,
7391
+ w: boxWidth,
7392
+ h: boxHeight,
7393
+ label,
7394
+ subtitle,
7395
+ labelSize: size,
7396
+ smallSize,
7397
+ font,
7398
+ weight,
7399
+ lineHeight,
7400
+ color: data.color,
7401
+ isHovered: isActuallyHovered
7402
+ });
7403
+ }
7404
+ if (!flushScheduled) {
7405
+ flushScheduled = true;
7406
+ queueMicrotask(() => {
7407
+ flushScheduled = false;
7408
+ flushTooltips();
7409
+ });
7410
+ }
7296
7411
  }
7297
7412
  function SigmaRefCapture({
7298
7413
  onReady
@@ -7305,6 +7420,14 @@ function SigmaRefCapture({
7305
7420
  onReady(sigma);
7306
7421
  }
7307
7422
  }, [sigma, onReady]);
7423
+ t.useEffect(() => {
7424
+ const s = sigma;
7425
+ const handler = () => resetLabelGrid();
7426
+ s.on("beforeRender", handler);
7427
+ return () => {
7428
+ s.off("beforeRender", handler);
7429
+ };
7430
+ }, [sigma]);
7308
7431
  return null;
7309
7432
  }
7310
7433
  function GraphEventHandler({
@@ -7558,6 +7681,7 @@ const GraphCanvas = t.memo(
7558
7681
  labelFont: LABEL_FONT,
7559
7682
  labelColor: { color: LABEL_COLOR },
7560
7683
  labelSize: LABEL_SIZE,
7684
+ defaultDrawNodeLabel: drawNodeLabel,
7561
7685
  defaultDrawNodeHover: drawNodeHover,
7562
7686
  allowInvalidContainer: true,
7563
7687
  zIndex: zIndexEnabled,
@@ -9120,6 +9244,9 @@ exports.NODE_SIZE_MIN = NODE_SIZE_MIN;
9120
9244
  exports.NODE_SIZE_MULTIPLIERS = NODE_SIZE_MULTIPLIERS;
9121
9245
  exports.ZOOM_SIZE_EXPONENT = ZOOM_SIZE_EXPONENT;
9122
9246
  exports.drawNodeHover = drawNodeHover;
9247
+ exports.drawNodeLabel = drawNodeLabel;
9248
+ exports.flushTooltips = flushTooltips;
9249
+ exports.resetLabelGrid = resetLabelGrid;
9123
9250
  exports.setHoveredNodeKey = setHoveredNodeKey;
9124
9251
  exports.useGraphInstance = useGraphInstance;
9125
9252
  exports.useGraphVisuals = useGraphVisuals;