Browse Source

fix eventMap redrawing & re-add mouseovertext

master
limina1 1 year ago
parent
commit
898addae87
  1. 336
      pnpm-lock.yaml
  2. 8
      src/app.css
  3. 182
      src/lib/components/EventNetwork.svelte

336
pnpm-lock.yaml

@ -29,6 +29,9 @@ importers:
asciidoctor: asciidoctor:
specifier: ^3.0.4 specifier: ^3.0.4
version: 3.0.4(chokidar@3.6.0) version: 3.0.4(chokidar@3.6.0)
d3:
specifier: ^7.9.0
version: 7.9.0
he: he:
specifier: ^1.2.0 specifier: ^1.2.0
version: 1.2.0 version: 1.2.0
@ -57,6 +60,9 @@ importers:
'@sveltejs/adapter-auto': '@sveltejs/adapter-auto':
specifier: ^3.1.1 specifier: ^3.1.1
version: 3.2.4(@sveltejs/kit@2.5.25(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.2(@types/node@22.5.4)))(svelte@4.2.19)(vite@5.4.2(@types/node@22.5.4))) version: 3.2.4(@sveltejs/kit@2.5.25(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.2(@types/node@22.5.4)))(svelte@4.2.19)(vite@5.4.2(@types/node@22.5.4)))
'@sveltejs/adapter-static':
specifier: ^3.0.6
version: 3.0.6(@sveltejs/kit@2.5.25(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.2(@types/node@22.5.4)))(svelte@4.2.19)(vite@5.4.2(@types/node@22.5.4)))
'@sveltejs/kit': '@sveltejs/kit':
specifier: ^2.4.3 specifier: ^2.4.3
version: 2.5.25(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.2(@types/node@22.5.4)))(svelte@4.2.19)(vite@5.4.2(@types/node@22.5.4)) version: 2.5.25(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.2(@types/node@22.5.4)))(svelte@4.2.19)(vite@5.4.2(@types/node@22.5.4))
@ -538,6 +544,11 @@ packages:
peerDependencies: peerDependencies:
'@sveltejs/kit': ^2.0.0 '@sveltejs/kit': ^2.0.0
'@sveltejs/adapter-static@3.0.6':
resolution: {integrity: sha512-MGJcesnJWj7FxDcB/GbrdYD3q24Uk0PIL4QIX149ku+hlJuj//nxUbb0HxUTpjkecWfHjVveSUnUaQWnPRXlpg==}
peerDependencies:
'@sveltejs/kit': ^2.0.0
'@sveltejs/kit@2.5.25': '@sveltejs/kit@2.5.25':
resolution: {integrity: sha512-5hBSEN8XEjDZ5+2bHkFh8Z0QyOk0C187cyb12aANe1c8aeKbfu5ZD5XaC2vEH4h0alJFDXPdUkXQBmeeXeMr1A==} resolution: {integrity: sha512-5hBSEN8XEjDZ5+2bHkFh8Z0QyOk0C187cyb12aANe1c8aeKbfu5ZD5XaC2vEH4h0alJFDXPdUkXQBmeeXeMr1A==}
engines: {node: '>=18.13'} engines: {node: '>=18.13'}
@ -796,6 +807,10 @@ packages:
resolution: {integrity: sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==} resolution: {integrity: sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==}
engines: {node: '>= 6'} engines: {node: '>= 6'}
commander@7.2.0:
resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==}
engines: {node: '>= 10'}
commander@9.5.0: commander@9.5.0:
resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==}
engines: {node: ^12.20.0 || >=14} engines: {node: ^12.20.0 || >=14}
@ -823,6 +838,133 @@ packages:
engines: {node: '>=4'} engines: {node: '>=4'}
hasBin: true hasBin: true
d3-array@3.2.4:
resolution: {integrity: sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==}
engines: {node: '>=12'}
d3-axis@3.0.0:
resolution: {integrity: sha512-IH5tgjV4jE/GhHkRV0HiVYPDtvfjHQlQfJHs0usq7M30XcSBvOotpmH1IgkcXsO/5gEQZD43B//fc7SRT5S+xw==}
engines: {node: '>=12'}
d3-brush@3.0.0:
resolution: {integrity: sha512-ALnjWlVYkXsVIGlOsuWH1+3udkYFI48Ljihfnh8FZPF2QS9o+PzGLBslO0PjzVoHLZ2KCVgAM8NVkXPJB2aNnQ==}
engines: {node: '>=12'}
d3-chord@3.0.1:
resolution: {integrity: sha512-VE5S6TNa+j8msksl7HwjxMHDM2yNK3XCkusIlpX5kwauBfXuyLAtNg9jCp/iHH61tgI4sb6R/EIMWCqEIdjT/g==}
engines: {node: '>=12'}
d3-color@3.1.0:
resolution: {integrity: sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==}
engines: {node: '>=12'}
d3-contour@4.0.2:
resolution: {integrity: sha512-4EzFTRIikzs47RGmdxbeUvLWtGedDUNkTcmzoeyg4sP/dvCexO47AaQL7VKy/gul85TOxw+IBgA8US2xwbToNA==}
engines: {node: '>=12'}
d3-delaunay@6.0.4:
resolution: {integrity: sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==}
engines: {node: '>=12'}
d3-dispatch@3.0.1:
resolution: {integrity: sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==}
engines: {node: '>=12'}
d3-drag@3.0.0:
resolution: {integrity: sha512-pWbUJLdETVA8lQNJecMxoXfH6x+mO2UQo8rSmZ+QqxcbyA3hfeprFgIT//HW2nlHChWeIIMwS2Fq+gEARkhTkg==}
engines: {node: '>=12'}
d3-dsv@3.0.1:
resolution: {integrity: sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==}
engines: {node: '>=12'}
hasBin: true
d3-ease@3.0.1:
resolution: {integrity: sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==}
engines: {node: '>=12'}
d3-fetch@3.0.1:
resolution: {integrity: sha512-kpkQIM20n3oLVBKGg6oHrUchHM3xODkTzjMoj7aWQFq5QEM+R6E4WkzT5+tojDY7yjez8KgCBRoj4aEr99Fdqw==}
engines: {node: '>=12'}
d3-force@3.0.0:
resolution: {integrity: sha512-zxV/SsA+U4yte8051P4ECydjD/S+qeYtnaIyAs9tgHCqfguma/aAQDjo85A9Z6EKhBirHRJHXIgJUlffT4wdLg==}
engines: {node: '>=12'}
d3-format@3.1.0:
resolution: {integrity: sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==}
engines: {node: '>=12'}
d3-geo@3.1.1:
resolution: {integrity: sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==}
engines: {node: '>=12'}
d3-hierarchy@3.1.2:
resolution: {integrity: sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==}
engines: {node: '>=12'}
d3-interpolate@3.0.1:
resolution: {integrity: sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==}
engines: {node: '>=12'}
d3-path@3.1.0:
resolution: {integrity: sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==}
engines: {node: '>=12'}
d3-polygon@3.0.1:
resolution: {integrity: sha512-3vbA7vXYwfe1SYhED++fPUQlWSYTTGmFmQiany/gdbiWgU/iEyQzyymwL9SkJjFFuCS4902BSzewVGsHHmHtXg==}
engines: {node: '>=12'}
d3-quadtree@3.0.1:
resolution: {integrity: sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==}
engines: {node: '>=12'}
d3-random@3.0.1:
resolution: {integrity: sha512-FXMe9GfxTxqd5D6jFsQ+DJ8BJS4E/fT5mqqdjovykEB2oFbTMDVdg1MGFxfQW+FBOGoB++k8swBrgwSHT1cUXQ==}
engines: {node: '>=12'}
d3-scale-chromatic@3.1.0:
resolution: {integrity: sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==}
engines: {node: '>=12'}
d3-scale@4.0.2:
resolution: {integrity: sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==}
engines: {node: '>=12'}
d3-selection@3.0.0:
resolution: {integrity: sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==}
engines: {node: '>=12'}
d3-shape@3.2.0:
resolution: {integrity: sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==}
engines: {node: '>=12'}
d3-time-format@4.1.0:
resolution: {integrity: sha512-dJxPBlzC7NugB2PDLwo9Q8JiTR3M3e4/XANkreKSUxF8vvXKqm1Yfq4Q5dl8budlunRVlUUaDUgFt7eA8D6NLg==}
engines: {node: '>=12'}
d3-time@3.1.0:
resolution: {integrity: sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==}
engines: {node: '>=12'}
d3-timer@3.0.1:
resolution: {integrity: sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==}
engines: {node: '>=12'}
d3-transition@3.0.1:
resolution: {integrity: sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==}
engines: {node: '>=12'}
peerDependencies:
d3-selection: 2 - 3
d3-zoom@3.0.0:
resolution: {integrity: sha512-b8AmV3kfQaqWAuacbPuNbL6vahnOJflOhexLzMMNLga62+/nh0JzvJ0aO/5a5MVgUFGS7Hu1P9P03o3fJkDCyw==}
engines: {node: '>=12'}
d3@7.9.0:
resolution: {integrity: sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==}
engines: {node: '>=12'}
d@1.0.2: d@1.0.2:
resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==} resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==}
engines: {node: '>=0.12'} engines: {node: '>=0.12'}
@ -859,6 +1001,9 @@ packages:
resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
delaunator@5.0.1:
resolution: {integrity: sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==}
dequal@2.0.3: dequal@2.0.3:
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
engines: {node: '>=6'} engines: {node: '>=6'}
@ -1228,6 +1373,10 @@ packages:
resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
engines: {node: '>=10.17.0'} engines: {node: '>=10.17.0'}
iconv-lite@0.6.3:
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
engines: {node: '>=0.10.0'}
ignore@5.3.2: ignore@5.3.2:
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
engines: {node: '>= 4'} engines: {node: '>= 4'}
@ -1250,6 +1399,10 @@ packages:
inherits@2.0.4: inherits@2.0.4:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
internmap@2.0.3:
resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==}
engines: {node: '>=12'}
is-binary-path@2.1.0: is-binary-path@2.1.0:
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
engines: {node: '>=8'} engines: {node: '>=8'}
@ -1802,6 +1955,9 @@ packages:
deprecated: Rimraf versions prior to v4 are no longer supported deprecated: Rimraf versions prior to v4 are no longer supported
hasBin: true hasBin: true
robust-predicates@3.0.2:
resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==}
rollup@4.21.2: rollup@4.21.2:
resolution: {integrity: sha512-e3TapAgYf9xjdLvKQCkQTnbTKd4a6jwlpQSJJFokHGaX2IVjoEqkIIhiQfqsi0cdwlOD+tQGuOd5AJkc5RngBw==} resolution: {integrity: sha512-e3TapAgYf9xjdLvKQCkQTnbTKd4a6jwlpQSJJFokHGaX2IVjoEqkIIhiQfqsi0cdwlOD+tQGuOd5AJkc5RngBw==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'} engines: {node: '>=18.0.0', npm: '>=8.0.0'}
@ -1810,10 +1966,16 @@ packages:
run-parallel@1.2.0: run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
rw@1.3.3:
resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==}
sade@1.8.1: sade@1.8.1:
resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==} resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
engines: {node: '>=6'} engines: {node: '>=6'}
safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
sander@0.5.1: sander@0.5.1:
resolution: {integrity: sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==} resolution: {integrity: sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==}
@ -2569,6 +2731,10 @@ snapshots:
'@sveltejs/kit': 2.5.25(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.2(@types/node@22.5.4)))(svelte@4.2.19)(vite@5.4.2(@types/node@22.5.4)) '@sveltejs/kit': 2.5.25(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.2(@types/node@22.5.4)))(svelte@4.2.19)(vite@5.4.2(@types/node@22.5.4))
import-meta-resolve: 4.1.0 import-meta-resolve: 4.1.0
'@sveltejs/adapter-static@3.0.6(@sveltejs/kit@2.5.25(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.2(@types/node@22.5.4)))(svelte@4.2.19)(vite@5.4.2(@types/node@22.5.4)))':
dependencies:
'@sveltejs/kit': 2.5.25(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.2(@types/node@22.5.4)))(svelte@4.2.19)(vite@5.4.2(@types/node@22.5.4))
'@sveltejs/kit@2.5.25(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.2(@types/node@22.5.4)))(svelte@4.2.19)(vite@5.4.2(@types/node@22.5.4))': '@sveltejs/kit@2.5.25(@sveltejs/vite-plugin-svelte@3.1.2(svelte@4.2.19)(vite@5.4.2(@types/node@22.5.4)))(svelte@4.2.19)(vite@5.4.2(@types/node@22.5.4))':
dependencies: dependencies:
'@sveltejs/vite-plugin-svelte': 3.1.2(svelte@4.2.19)(vite@5.4.2(@types/node@22.5.4)) '@sveltejs/vite-plugin-svelte': 3.1.2(svelte@4.2.19)(vite@5.4.2(@types/node@22.5.4))
@ -2854,6 +3020,8 @@ snapshots:
commander@5.1.0: {} commander@5.1.0: {}
commander@7.2.0: {}
commander@9.5.0: {} commander@9.5.0: {}
concat-map@0.0.1: {} concat-map@0.0.1: {}
@ -2878,6 +3046,158 @@ snapshots:
cssesc@3.0.0: {} cssesc@3.0.0: {}
d3-array@3.2.4:
dependencies:
internmap: 2.0.3
d3-axis@3.0.0: {}
d3-brush@3.0.0:
dependencies:
d3-dispatch: 3.0.1
d3-drag: 3.0.0
d3-interpolate: 3.0.1
d3-selection: 3.0.0
d3-transition: 3.0.1(d3-selection@3.0.0)
d3-chord@3.0.1:
dependencies:
d3-path: 3.1.0
d3-color@3.1.0: {}
d3-contour@4.0.2:
dependencies:
d3-array: 3.2.4
d3-delaunay@6.0.4:
dependencies:
delaunator: 5.0.1
d3-dispatch@3.0.1: {}
d3-drag@3.0.0:
dependencies:
d3-dispatch: 3.0.1
d3-selection: 3.0.0
d3-dsv@3.0.1:
dependencies:
commander: 7.2.0
iconv-lite: 0.6.3
rw: 1.3.3
d3-ease@3.0.1: {}
d3-fetch@3.0.1:
dependencies:
d3-dsv: 3.0.1
d3-force@3.0.0:
dependencies:
d3-dispatch: 3.0.1
d3-quadtree: 3.0.1
d3-timer: 3.0.1
d3-format@3.1.0: {}
d3-geo@3.1.1:
dependencies:
d3-array: 3.2.4
d3-hierarchy@3.1.2: {}
d3-interpolate@3.0.1:
dependencies:
d3-color: 3.1.0
d3-path@3.1.0: {}
d3-polygon@3.0.1: {}
d3-quadtree@3.0.1: {}
d3-random@3.0.1: {}
d3-scale-chromatic@3.1.0:
dependencies:
d3-color: 3.1.0
d3-interpolate: 3.0.1
d3-scale@4.0.2:
dependencies:
d3-array: 3.2.4
d3-format: 3.1.0
d3-interpolate: 3.0.1
d3-time: 3.1.0
d3-time-format: 4.1.0
d3-selection@3.0.0: {}
d3-shape@3.2.0:
dependencies:
d3-path: 3.1.0
d3-time-format@4.1.0:
dependencies:
d3-time: 3.1.0
d3-time@3.1.0:
dependencies:
d3-array: 3.2.4
d3-timer@3.0.1: {}
d3-transition@3.0.1(d3-selection@3.0.0):
dependencies:
d3-color: 3.1.0
d3-dispatch: 3.0.1
d3-ease: 3.0.1
d3-interpolate: 3.0.1
d3-selection: 3.0.0
d3-timer: 3.0.1
d3-zoom@3.0.0:
dependencies:
d3-dispatch: 3.0.1
d3-drag: 3.0.0
d3-interpolate: 3.0.1
d3-selection: 3.0.0
d3-transition: 3.0.1(d3-selection@3.0.0)
d3@7.9.0:
dependencies:
d3-array: 3.2.4
d3-axis: 3.0.0
d3-brush: 3.0.0
d3-chord: 3.0.1
d3-color: 3.1.0
d3-contour: 4.0.2
d3-delaunay: 6.0.4
d3-dispatch: 3.0.1
d3-drag: 3.0.0
d3-dsv: 3.0.1
d3-ease: 3.0.1
d3-fetch: 3.0.1
d3-force: 3.0.0
d3-format: 3.1.0
d3-geo: 3.1.1
d3-hierarchy: 3.1.2
d3-interpolate: 3.0.1
d3-path: 3.1.0
d3-polygon: 3.0.1
d3-quadtree: 3.0.1
d3-random: 3.0.1
d3-scale: 4.0.2
d3-scale-chromatic: 3.1.0
d3-selection: 3.0.0
d3-shape: 3.2.0
d3-time: 3.1.0
d3-time-format: 4.1.0
d3-timer: 3.0.1
d3-transition: 3.0.1(d3-selection@3.0.0)
d3-zoom: 3.0.0
d@1.0.2: d@1.0.2:
dependencies: dependencies:
es5-ext: 0.10.64 es5-ext: 0.10.64
@ -2903,6 +3223,10 @@ snapshots:
es-errors: 1.3.0 es-errors: 1.3.0
gopd: 1.0.1 gopd: 1.0.1
delaunator@5.0.1:
dependencies:
robust-predicates: 3.0.2
dequal@2.0.3: {} dequal@2.0.3: {}
detect-indent@6.1.0: {} detect-indent@6.1.0: {}
@ -3355,6 +3679,10 @@ snapshots:
human-signals@2.1.0: {} human-signals@2.1.0: {}
iconv-lite@0.6.3:
dependencies:
safer-buffer: 2.1.2
ignore@5.3.2: {} ignore@5.3.2: {}
import-fresh@3.3.0: import-fresh@3.3.0:
@ -3373,6 +3701,8 @@ snapshots:
inherits@2.0.4: {} inherits@2.0.4: {}
internmap@2.0.3: {}
is-binary-path@2.1.0: is-binary-path@2.1.0:
dependencies: dependencies:
binary-extensions: 2.3.0 binary-extensions: 2.3.0
@ -3873,6 +4203,8 @@ snapshots:
dependencies: dependencies:
glob: 7.2.3 glob: 7.2.3
robust-predicates@3.0.2: {}
rollup@4.21.2: rollup@4.21.2:
dependencies: dependencies:
'@types/estree': 1.0.5 '@types/estree': 1.0.5
@ -3899,10 +4231,14 @@ snapshots:
dependencies: dependencies:
queue-microtask: 1.2.3 queue-microtask: 1.2.3
rw@1.3.3: {}
sade@1.8.1: sade@1.8.1:
dependencies: dependencies:
mri: 1.2.0 mri: 1.2.0
safer-buffer@2.1.2: {}
sander@0.5.1: sander@0.5.1:
dependencies: dependencies:
es6-promise: 3.3.1 es6-promise: 3.3.1

8
src/app.css

@ -150,8 +150,10 @@
.network-link-leather { .network-link-leather {
@apply stroke-gray-400 dark:stroke-gray-600 fill-gray-400 dark:fill-gray-600; @apply stroke-gray-400 dark:stroke-gray-600 fill-gray-400 dark:fill-gray-600;
} }
.network-node-leather {
.text-leather { @apply stroke-gray-800;
@apply fill-gray-800 dark:fill-gray-300; }
.network-node-content {
@apply fill-[#d6c1a8];
} }
} }

182
src/lib/components/EventNetwork.svelte

@ -8,19 +8,18 @@
let svg: SVGSVGElement; let svg: SVGSVGElement;
let isDarkMode = false; let isDarkMode = false;
const nodeRadius = 20; const nodeRadius = 20;
const dragRadius = 45; const dragRadius = 10;
const linkDistance = 120; const linkDistance = 5;
const warmupClickEnergy = 0.9; // Energy to restart simulation on drag
let container: HTMLDivElement; let container: HTMLDivElement;
let width: number; let width: number;
let height: number; let height: number;
// Reactive statement for container dimensions
$: if (container) { $: if (container) {
width = container.clientWidth || 800; width = container.clientWidth || 800;
height = container.clientHeight || 600; height = container.clientHeight || 600;
} }
// Type definitions for network components
interface NetworkNode extends d3.SimulationNodeDatum { interface NetworkNode extends d3.SimulationNodeDatum {
id: string; id: string;
event?: NDKEvent; event?: NDKEvent;
@ -41,8 +40,6 @@
target: NetworkNode; target: NetworkNode;
isSequential: boolean; isSequential: boolean;
} }
// Create an efficient event map for O(1) lookups
function createEventMap(events: NDKEvent[]): Map<string, NDKEvent> { function createEventMap(events: NDKEvent[]): Map<string, NDKEvent> {
return new Map(events.map((event) => [event.id, event])); return new Map(events.map((event) => [event.id, event]));
} }
@ -74,7 +71,9 @@
function getEventColor(eventId: string): string { function getEventColor(eventId: string): string {
const num = parseInt(eventId.slice(0, 4), 16); const num = parseInt(eventId.slice(0, 4), 16);
const hue = num % 360; const hue = num % 360;
return `hsl(${hue}, 70%, 75%)`; const saturation = 70;
const lightness = 75;
return `hsl(${hue}, ${saturation}%, ${lightness}%)`;
} }
function generateGraph(events: NDKEvent[]): { function generateGraph(events: NDKEvent[]): {
@ -84,6 +83,8 @@
const nodes: NetworkNode[] = []; const nodes: NetworkNode[] = [];
const links: NetworkLink[] = []; const links: NetworkLink[] = [];
const nodeMap = new Map<string, NetworkNode>(); const nodeMap = new Map<string, NetworkNode>();
// Create event lookup map - O(n) operation done once
const eventMap = createEventMap(events); const eventMap = createEventMap(events);
const indexEvents = events.filter((e) => e.kind === 30040); const indexEvents = events.filter((e) => e.kind === 30040);
@ -99,7 +100,7 @@
contentRefs.forEach((tag, idx) => { contentRefs.forEach((tag, idx) => {
if (!tag[1]) return; if (!tag[1]) return;
// Use O(1) lookup instead of O(n) find operation // O(1) lookup instead of O(n) search
const targetEvent = eventMap.get(tag[1]); const targetEvent = eventMap.get(tag[1]);
if (!targetEvent) return; if (!targetEvent) return;
@ -123,9 +124,8 @@
return { nodes, links }; return { nodes, links };
} }
function setupDragHandlers( function setupDragHandlers(
simulation: d3.Simulation<NetworkNode, undefined>, simulation: d3.Simulation<NetworkNode, NetworkLink>,
) { ) {
// Create drag behavior with proper typing // Create drag behavior with proper typing
const dragBehavior = d3 const dragBehavior = d3
@ -137,7 +137,8 @@
d: NetworkNode, d: NetworkNode,
) => { ) => {
// Warm up simulation when drag starts // Warm up simulation when drag starts
if (!event.active) simulation.alphaTarget(0.3).restart(); if (!event.active)
simulation.alphaTarget(warmupClickEnergy).restart();
// Fix node position during drag // Fix node position during drag
d.fx = d.x; d.fx = d.x;
d.fy = d.y; d.fy = d.y;
@ -167,10 +168,8 @@
d.fy = null; d.fy = null;
}, },
); );
return dragBehavior; return dragBehavior;
} }
function drawNetwork() { function drawNetwork() {
if (!svg || !events?.length) return; if (!svg || !events?.length) return;
@ -178,22 +177,21 @@
if (!nodes.length) return; if (!nodes.length) return;
const svgElement = d3.select(svg).attr("viewBox", `0 0 ${width} ${height}`); const svgElement = d3.select(svg).attr("viewBox", `0 0 ${width} ${height}`);
// Set up zoom behavior
let g = svgElement.append("g");
const zoom = d3
.zoom<SVGSVGElement, unknown>()
.scaleExtent([0.4, 9])
.on("zoom", (event) => {
g.attr("transform", event.transform);
});
let g = svgElement.select("g"); svgElement.call(zoom);
// Only create the base group and zoom behavior if it doesn't exist
if (g.empty()) { if (g.empty()) {
const zoom = d3
.zoom<SVGSVGElement, unknown>()
.scaleExtent([0.1, 4])
.on("zoom", (event) => {
g.attr("transform", event.transform);
});
svgElement.call(zoom);
g = svgElement.append("g"); g = svgElement.append("g");
// Define arrow marker only once // Define arrow marker with black fill
const marker = g const marker = g
.append("defs") .append("defs")
.selectAll("marker") .selectAll("marker")
@ -210,10 +208,9 @@
marker marker
.append("path") .append("path")
.attr("d", "M -8,-5 L 0, 0 L -8, 5 Z") .attr("d", "M -8,-5 L 0, 0 L -8, 5 Z")
.attr("class", "network-link-leather"); .attr("class", "network-link-leather"); // Black fill for arrowhead
} }
// Force simulation setup
// Set up force simulation
const simulation = d3 const simulation = d3
.forceSimulation<NetworkNode>(nodes) .forceSimulation<NetworkNode>(nodes)
.force( .force(
@ -223,16 +220,17 @@
.id((d) => d.id) .id((d) => d.id)
.distance(linkDistance), .distance(linkDistance),
) )
.force("charge", d3.forceManyBody().strength(-500)) .force("charge", d3.forceManyBody<NetworkNode>().strength(-1000))
.force("center", d3.forceCenter(width / 2, height / 2)) .force("center", d3.forceCenter(width / 2, height / 2))
.force("x", d3.forceX(width / 2).strength(0.1)) .force("x", d3.forceX<NetworkNode>(width / 2).strength(0.1))
.force("y", d3.forceY(height / 2).strength(0.1)) .force("y", d3.forceY<NetworkNode>(height / 2).strength(0.1))
.force("collision", d3.forceCollide().radius(nodeRadius * 2.5)); .force(
"collision",
// Create drag handler d3.forceCollide<NetworkNode>().radius(nodeRadius * 2.5),
);
const dragHandler = setupDragHandlers(simulation); const dragHandler = setupDragHandlers(simulation);
// Update links with enter/update/exit pattern // Create links
const link = g const link = g
.selectAll<SVGPathElement, NetworkLink>("path.link") .selectAll<SVGPathElement, NetworkLink>("path.link")
.data(links, (d: NetworkLink) => `${d.source.id}-${d.target.id}`) .data(links, (d: NetworkLink) => `${d.source.id}-${d.target.id}`)
@ -240,15 +238,15 @@
(enter) => (enter) =>
enter enter
.append("path") .append("path")
.attr("class", "network-link-leather link") .attr("class", "network-link-leather")
.attr("stroke-width", 2) .attr("stroke-width", 2)
.attr("fill", "none") .attr("fill", "transparent")
.attr("marker-end", "url(#arrowhead)"), .attr("marker-end", "url(#arrowhead)"),
(update) => update, (update) => update,
(exit) => exit.remove(), (exit) => exit.remove(),
); );
// Update nodes with enter/update/exit pattern // Create nodes
const node = g const node = g
.selectAll<SVGGElement, NetworkNode>("g.node") .selectAll<SVGGElement, NetworkNode>("g.node")
.data(nodes, (d: NetworkNode) => d.id) .data(nodes, (d: NetworkNode) => d.id)
@ -259,28 +257,33 @@
.attr("class", "node network-node-leather") .attr("class", "node network-node-leather")
.call(dragHandler); .call(dragHandler);
// Add drag circle // add drag circle
nodeEnter nodeEnter
.append("circle") .append("circle")
.attr("r", dragRadius) .attr("r", nodeRadius * 2.5)
.attr("fill", "transparent") .attr("fill", "transparent")
.attr("stroke", "transparent")
.style("cursor", "move"); .style("cursor", "move");
// Add visible node circle // add visual circle, stroke based on current theme
nodeEnter nodeEnter
.append("circle") .append("circle")
.attr("r", nodeRadius) .attr("r", nodeRadius)
.attr("stroke", "#000000") .attr("class", (d: NetworkNode) =>
!d.isContainer
? "network-node-leather network-node-content"
: "network-node-leather",
)
.attr("stroke-width", 2); .attr("stroke-width", 2);
// Add text labels // add text labels
nodeEnter nodeEnter
.append("text") .append("text")
.attr("dy", "0.35em") .attr("dy", "0.35em")
.attr("text-anchor", "middle") .attr("text-anchor", "middle")
.attr("fill", "#000000") .attr("fill", "black")
.attr("font-size", "12px") .attr("font-size", "12px");
.attr("font-weight", "bold"); // .attr("font-weight", "bold");
return nodeEnter; return nodeEnter;
}, },
@ -288,39 +291,88 @@
(exit) => exit.remove(), (exit) => exit.remove(),
); );
// Update node appearances // Add text labels
node node
.select("circle:nth-child(2)") .select("circle:nth-child(2)")
.attr("fill", (d) => .attr("fill", (d: NetworkNode) =>
!d.isContainer !d.isContainer
? isDarkMode ? isDarkMode
? "#342718" ? "#FFFFFF"
: "#d6c1a8" : "network-link-leather"
: getEventColor(d.id), : getEventColor(d.id),
); );
node.select("text").text((d) => (d.isContainer ? "I" : "C")); node.select("text").text((d: NetworkNode) => (d.isContainer ? "I" : "C"));
// Add tooltips
const tooltip = d3
.select("body")
.append("div")
.attr(
"class",
"fixed hidden bg-primary-0 dark:bg-primary-1000 " +
"text-gray-800 dark:text-gray-300 " +
"p-4 rounded shadow-lg border border-gray-200 dark:border-gray-800 " +
"transition-colors duration-200",
)
.style("z-index", 1000);
node
.on("mouseover", function (event, d) {
tooltip
.style("display", "block")
.html(
`
<div class="space-y-2">
<div class="font-bold text-base">${d.title}</div>
<div class="text-gray-600 dark:text-gray-400 text-sm">
${d.type} (${d.isContainer ? "30040" : "30041"})
</div>
<div class="text-gray-600 dark:text-gray-400 text-sm overflow-hidden text-ellipsis">
ID: ${d.id}
</div>
${
d.content
? `
<div class="mt-2 text-xs bg-gray-100 dark:bg-gray-800 p-2 rounded overflow-auto max-h-40">
${d.content}
</div>
`
: ""
}
</div>
`,
)
.style("left", event.pageX - 10 + "px")
.style("top", event.pageY + 10 + "px");
})
.on("mousemove", function (event) {
tooltip
.style("left", event.pageX + 10 + "px")
.style("top", event.pageY - 10 + "px");
})
.on("mouseout", () => {
tooltip.style("display", "none");
});
// Handle simulation updates // Handle simulation ticks
simulation.on("tick", () => { simulation.on("tick", () => {
// Update link positions
link.attr("d", (d) => { link.attr("d", (d) => {
const dx = d.target.x! - d.source.x!; const dx = d.target.x! - d.source.x!;
const dy = d.target.y! - d.source.y!; const dy = d.target.y! - d.source.y!;
const angle = Math.atan2(dy, dx); const angle = Math.atan2(dy, dx);
// Adjust start and end points to prevent overlap with nodes
const startX = d.source.x! + nodeRadius * Math.cos(angle); const startX = d.source.x! + nodeRadius * Math.cos(angle);
const startY = d.source.y! + nodeRadius * Math.sin(angle); const startY = d.source.y! + nodeRadius * Math.sin(angle);
const endX = d.target.x! - nodeRadius * Math.cos(angle); const endX = d.target.x! - nodeRadius * Math.cos(angle);
const endY = d.target.y! - nodeRadius * Math.sin(angle); const endY = d.target.y! - nodeRadius * Math.sin(angle);
return `M${startX},${startY}L${endX},${endY}`; return `M${startX},${startY}L${endX},${endY}`;
}); });
// Update node positions
node.attr("transform", (d) => `translate(${d.x},${d.y})`); node.attr("transform", (d) => `translate(${d.x},${d.y})`);
}); });
} }
// Setup and cleanup
onMount(() => { onMount(() => {
isDarkMode = document.body.classList.contains("dark"); isDarkMode = document.body.classList.contains("dark");
@ -337,13 +389,12 @@
}); });
}); });
// Watch for container size changes
const resizeObserver = new ResizeObserver((entries) => { const resizeObserver = new ResizeObserver((entries) => {
for (const entry of entries) { for (const entry of entries) {
width = entry.contentRect.width; width = entry.contentRect.width;
height = entry.contentRect.height || width * 0.6; height = entry.contentRect.height * 1 || width * 1.0;
} }
if (svg) drawNetwork(); // if (svg) drawNetwork();
}); });
// Start observers // Start observers
@ -352,15 +403,13 @@
attributeFilter: ["class"], attributeFilter: ["class"],
}); });
resizeObserver.observe(container); resizeObserver.observe(container);
// Clean up
// Cleanup function
return () => { return () => {
themeObserver.disconnect(); themeObserver.disconnect();
resizeObserver.disconnect(); resizeObserver.disconnect();
}; };
}); });
// Reactive redaw
// Reactive redraw
$: { $: {
if (svg && events?.length) { if (svg && events?.length) {
drawNetwork(); drawNetwork();
@ -369,7 +418,7 @@
</script> </script>
# /lib/components/EventNetwork.svelte # /lib/components/EventNetwork.svelte
<div class="w-full h-[600px]" bind:this={container}> <div class="w-full h-[1200px]" bind:this={container}>
<svg <svg
bind:this={svg} bind:this={svg}
class="w-full h-full border border-gray-300 dark:border-gray-700 rounded" class="w-full h-full border border-gray-300 dark:border-gray-700 rounded"
@ -423,3 +472,6 @@
</ul> </ul>
</div> </div>
</div> </div>
<style>
</style>

Loading…
Cancel
Save