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: @@ -29,6 +29,9 @@ importers:
asciidoctor:
specifier: ^3.0.4
version: 3.0.4(chokidar@3.6.0)
d3:
specifier: ^7.9.0
version: 7.9.0
he:
specifier: ^1.2.0
version: 1.2.0
@ -57,6 +60,9 @@ importers: @@ -57,6 +60,9 @@ importers:
'@sveltejs/adapter-auto':
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)))
'@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':
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))
@ -538,6 +544,11 @@ packages: @@ -538,6 +544,11 @@ packages:
peerDependencies:
'@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':
resolution: {integrity: sha512-5hBSEN8XEjDZ5+2bHkFh8Z0QyOk0C187cyb12aANe1c8aeKbfu5ZD5XaC2vEH4h0alJFDXPdUkXQBmeeXeMr1A==}
engines: {node: '>=18.13'}
@ -796,6 +807,10 @@ packages: @@ -796,6 +807,10 @@ packages:
resolution: {integrity: sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==}
engines: {node: '>= 6'}
commander@7.2.0:
resolution: {integrity: sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==}
engines: {node: '>= 10'}
commander@9.5.0:
resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==}
engines: {node: ^12.20.0 || >=14}
@ -823,6 +838,133 @@ packages: @@ -823,6 +838,133 @@ packages:
engines: {node: '>=4'}
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:
resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==}
engines: {node: '>=0.12'}
@ -859,6 +1001,9 @@ packages: @@ -859,6 +1001,9 @@ packages:
resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==}
engines: {node: '>= 0.4'}
delaunator@5.0.1:
resolution: {integrity: sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==}
dequal@2.0.3:
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
engines: {node: '>=6'}
@ -1228,6 +1373,10 @@ packages: @@ -1228,6 +1373,10 @@ packages:
resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==}
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:
resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==}
engines: {node: '>= 4'}
@ -1250,6 +1399,10 @@ packages: @@ -1250,6 +1399,10 @@ packages:
inherits@2.0.4:
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:
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
engines: {node: '>=8'}
@ -1802,6 +1955,9 @@ packages: @@ -1802,6 +1955,9 @@ packages:
deprecated: Rimraf versions prior to v4 are no longer supported
hasBin: true
robust-predicates@3.0.2:
resolution: {integrity: sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg==}
rollup@4.21.2:
resolution: {integrity: sha512-e3TapAgYf9xjdLvKQCkQTnbTKd4a6jwlpQSJJFokHGaX2IVjoEqkIIhiQfqsi0cdwlOD+tQGuOd5AJkc5RngBw==}
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
@ -1810,10 +1966,16 @@ packages: @@ -1810,10 +1966,16 @@ packages:
run-parallel@1.2.0:
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
rw@1.3.3:
resolution: {integrity: sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==}
sade@1.8.1:
resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
engines: {node: '>=6'}
safer-buffer@2.1.2:
resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==}
sander@0.5.1:
resolution: {integrity: sha512-3lVqBir7WuKDHGrKRDn/1Ye3kwpXaDOMsiRP1wd6wpZW56gJhsbp5RqQpA6JG/P+pkXizygnr1dKR8vzWaVsfA==}
@ -2569,6 +2731,10 @@ snapshots: @@ -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))
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))':
dependencies:
'@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: @@ -2854,6 +3020,8 @@ snapshots:
commander@5.1.0: {}
commander@7.2.0: {}
commander@9.5.0: {}
concat-map@0.0.1: {}
@ -2878,6 +3046,158 @@ snapshots: @@ -2878,6 +3046,158 @@ snapshots:
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:
dependencies:
es5-ext: 0.10.64
@ -2903,6 +3223,10 @@ snapshots: @@ -2903,6 +3223,10 @@ snapshots:
es-errors: 1.3.0
gopd: 1.0.1
delaunator@5.0.1:
dependencies:
robust-predicates: 3.0.2
dequal@2.0.3: {}
detect-indent@6.1.0: {}
@ -3355,6 +3679,10 @@ snapshots: @@ -3355,6 +3679,10 @@ snapshots:
human-signals@2.1.0: {}
iconv-lite@0.6.3:
dependencies:
safer-buffer: 2.1.2
ignore@5.3.2: {}
import-fresh@3.3.0:
@ -3373,6 +3701,8 @@ snapshots: @@ -3373,6 +3701,8 @@ snapshots:
inherits@2.0.4: {}
internmap@2.0.3: {}
is-binary-path@2.1.0:
dependencies:
binary-extensions: 2.3.0
@ -3873,6 +4203,8 @@ snapshots: @@ -3873,6 +4203,8 @@ snapshots:
dependencies:
glob: 7.2.3
robust-predicates@3.0.2: {}
rollup@4.21.2:
dependencies:
'@types/estree': 1.0.5
@ -3899,10 +4231,14 @@ snapshots: @@ -3899,10 +4231,14 @@ snapshots:
dependencies:
queue-microtask: 1.2.3
rw@1.3.3: {}
sade@1.8.1:
dependencies:
mri: 1.2.0
safer-buffer@2.1.2: {}
sander@0.5.1:
dependencies:
es6-promise: 3.3.1

8
src/app.css

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

182
src/lib/components/EventNetwork.svelte

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

Loading…
Cancel
Save