diff --git a/CLAUDE.md b/CLAUDE.md index 5d695b3..1de1157 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -101,9 +101,8 @@ Body: {"product_slug": "predictalytics", "version": "1.0.1", "download_url": "...", "sha256_hash": "...", "git_commit": "..."} ``` -Die Version in `src/Predictalytics.WinFormsHost/Predictalytics.WinFormsHost.csproj` -(``) muss dazu passen — sie ist es, die der Client als installierte -Version meldet. +Die Version in `Directory.Build.props` (``) muss dazu passen — sie ist +es, die der Client als installierte Version meldet. ### Fehlerbehandlung Antworten haben die Form `{"status":"error","error":{"code":"…"}}`. diff --git a/Directory.Build.props b/Directory.Build.props index 35999d1..fa65bdb 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -3,8 +3,8 @@ 1.0.0 - + net10.0 latest enable diff --git a/NewDesign.zip b/NewDesign.zip deleted file mode 100644 index 00115f2..0000000 Binary files a/NewDesign.zip and /dev/null differ diff --git a/Spike/Spike.csproj b/Spike/Spike.csproj deleted file mode 100644 index 64e34a8..0000000 --- a/Spike/Spike.csproj +++ /dev/null @@ -1,8 +0,0 @@ - - - Exe - net8.0 - enable - enable - - diff --git a/docs/API.md b/docs/API.md index 1482966..63ab148 100644 --- a/docs/API.md +++ b/docs/API.md @@ -1,10 +1,12 @@ # Predictalytics REST API — Referenz -> Stand: 2026-07-11 · Interne API ohne Authentifizierung (nur lokal betreiben!). -> Interaktive Doku: **`/swagger`** auf dem laufenden Server (Standalone-API und -> WinForms-Embedded-Server registrieren identische Endpoints über -> `ApiConfiguration.MapPredictalyticsEndpoints()` — dort ist die einzige Stelle, -> an der neue Endpoints registriert werden dürfen). +> Stand: 2026-08-23 · Interne API, nur lokal betreiben. +> **Lesende** Endpunkte sind ungeschützt, **steuernde** verlangen seit Phase 4 den +> Header `X-Predictalytics-Key`, sobald in den Einstellungen ein Token hinterlegt ist +> (siehe `ApiTokenFilter`; `GET /api/capabilities` meldet der WebUI den Ist-Zustand). +> Interaktive Doku: **`/swagger`** auf dem laufenden Server. Endpunkte werden +> ausschliesslich in `ApiConfiguration.MapPredictalyticsReadEndpoints()` bzw. +> `MapPredictalyticsControlEndpoints()` registriert — nur dort neue ergänzen. Konventionen: JSON mit camelCase-Feldnamen · Zeiten in UTC (ISO 8601) · Prozente auf 0–100-Skala · Beträge in USD · `WinRate` ist marktbasiert @@ -140,8 +142,8 @@ Jobs werden von den Workern abgearbeitet (Worker müssen laufen!). Status: | `GET /api/dev/verify-positions/{traderId}` | Vergleicht unsere `TraderPositions` mit Polymarkets `/positions`-API; Antwort: `mismatches[]`, `match`, `dbPositionsCount`, `apiPositionsCount` | > Ein früherer `POST /api/dev/repair-db` wurde entfernt (fehlerhaftes SQL, -> destruktiv). Reparatur läuft über den WinForms-Menüpunkt **Development → -> Recalculate All Traders**. +> destruktiv). Reparatur läuft über die Schaltfläche **Recalculate All Traders** +> in der Avalonia-Shell. --- diff --git a/docs/BETRIEB-Deploymentcenter.md b/docs/BETRIEB-Deploymentcenter.md index 2016422..c29c83e 100644 --- a/docs/BETRIEB-Deploymentcenter.md +++ b/docs/BETRIEB-Deploymentcenter.md @@ -9,7 +9,7 @@ Das **Deployment Center** (`https://dc.mhdf.de`, Schwester-Repo | LicenseLabrador auf `license.mhdf.de`, Ed25519-signierte Envelopes | Deployment Center, `POST /api/license/v1/validate`, Hardware-ID v2 | | — | UpdateService, Fehler-Stream und Bugtracker (neu) | -Die Anbindung sitzt im `Predictalytics.WinFormsHost` und referenziert das +Die Anbindung sitzt in `Predictalytics.Hosting` und referenziert das C#-SDK `Deploymentcenter.Client` aus dem Schwester-Repo: ``` @@ -209,10 +209,10 @@ Release Notes also auch dann, wenn die statische `latest.json` fehlt. ### Versionsstand -`Predictalytics.WinFormsHost.csproj` importiert `Deploymentcenter.BuildInfo.targets` -und erzeugt daraus zur Übersetzungszeit `Predictalytics.WinFormsHost.BuildInfo` +`Predictalytics.Hosting.csproj` importiert `Deploymentcenter.BuildInfo.targets` +und erzeugt daraus zur Übersetzungszeit `Predictalytics.Hosting.BuildInfo` mit `Version`, `GitCommit`, `GitCommitShort`, `BuildDateUtc`, `Channel` und -`Summary`. Quelle ist `` in derselben csproj — beim Release dort +`Summary`. Quelle ist `` in `Directory.Build.props` — beim Release dort hochziehen und mit ``` diff --git a/query.csx b/query.csx deleted file mode 100644 index 4150902..0000000 Binary files a/query.csx and /dev/null differ diff --git a/src/Predictalytics.Api/ApiConfiguration.cs b/src/Predictalytics.Api/ApiConfiguration.cs index 5607213..157f83d 100644 --- a/src/Predictalytics.Api/ApiConfiguration.cs +++ b/src/Predictalytics.Api/ApiConfiguration.cs @@ -1,49 +1,18 @@ using Predictalytics.Api.Endpoints; using Predictalytics.Api.Security; -using Predictalytics.Infrastructure; -using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Routing; -using Microsoft.Extensions.Configuration; using System; namespace Predictalytics.Api; /// -/// Configures the API WebApplication. Used by the embedded Kestrel server. +/// Registriert die Endpunkte der lokalen API. Den WebApplication-Aufbau selbst +/// (Kestrel, CORS, Swagger, Static Files) macht Predictalytics.Hosting — +/// hier stehen nur die Routen. /// public static class ApiConfiguration { - public static WebApplication ConfigureApi(WebApplicationBuilder builder, string? connectionStringOverride = null) - { - builder.Services.AddPredictalytics(builder.Configuration, connectionStringOverride); - builder.Services.AddEndpointsApiExplorer(); - builder.Services.AddSwaggerGen(c => c.SwaggerDoc("v1", - new() { Title = "Predictalytics Analytics API", Version = "v1" })); - var allowedOrigins = builder.Configuration.GetSection("ApiSettings:AllowedOrigins").Get() - ?? new[] { "http://localhost:5000" }; - builder.Services.AddCors(o => o.AddDefaultPolicy(p => - p.WithOrigins(allowedOrigins).AllowAnyMethod().AllowAnyHeader())); - - var app = builder.Build(); - - app.UseCors(); - app.UseSwagger(); - app.UseSwaggerUI(); - app.UseDefaultFiles(); - app.UseStaticFiles(new StaticFileOptions - { - // Internal dashboard: always revalidate so UI fixes reach the browser immediately. - OnPrepareResponse = ctx => ctx.Context.Response.Headers.CacheControl = "no-cache" - }); - - // Register both Read and Control endpoints for the local host - app.MapPredictalyticsReadEndpoints(); - app.MapPredictalyticsControlEndpoints(); - - return app; - } - /// /// Registers all Read-only endpoints designed for viewing and analysis. /// Safely exposed publicly since these endpoints perform no DB writes. diff --git a/src/Predictalytics.Api/Endpoints/DevEndpoints.cs b/src/Predictalytics.Api/Endpoints/DevEndpoints.cs index b279774..2aa435d 100644 --- a/src/Predictalytics.Api/Endpoints/DevEndpoints.cs +++ b/src/Predictalytics.Api/Endpoints/DevEndpoints.cs @@ -72,7 +72,7 @@ public static class DevEndpoints // its raw SQL referenced non-existent columns/tables (Trades.Type/Payout, // Traders.LastPositionsUpdatedAt, table "Jobs") and would have deleted ALL // TraderPositions including the pruned-history conserves. The supported - // repair path is the "Recalculate All Traders" action in the WinForms + // repair path is the "Recalculate All Traders" action in the Avalonia // Development menu (EmbeddedWebServer.RunRecalculateAllTradersAsync). } } diff --git a/src/Predictalytics.Api/Predictalytics.Api.csproj b/src/Predictalytics.Api/Predictalytics.Api.csproj index 058eebd..73a2316 100644 --- a/src/Predictalytics.Api/Predictalytics.Api.csproj +++ b/src/Predictalytics.Api/Predictalytics.Api.csproj @@ -2,14 +2,10 @@ Predictalytics.Api - + Library - - - - diff --git a/src/Predictalytics.Application/Interfaces/IAnalyticsService.cs b/src/Predictalytics.Application/Interfaces/IAnalyticsService.cs index b856e5a..d9401f2 100644 --- a/src/Predictalytics.Application/Interfaces/IAnalyticsService.cs +++ b/src/Predictalytics.Application/Interfaces/IAnalyticsService.cs @@ -16,7 +16,6 @@ public interface IAnalyticsService Task> GetShowcasesAsync(CancellationToken ct = default); /// Get list of all discovered traits. - Task> GetTraitsAsync(CancellationToken ct = default); /// Get a trader's details. Task GetTraderDetailAsync(int traderId, CancellationToken ct = default); diff --git a/src/Predictalytics.Application/Services/AnalyticsService.cs b/src/Predictalytics.Application/Services/AnalyticsService.cs index c19805d..9747421 100644 --- a/src/Predictalytics.Application/Services/AnalyticsService.cs +++ b/src/Predictalytics.Application/Services/AnalyticsService.cs @@ -242,13 +242,6 @@ public class AnalyticsService : IAnalyticsService return ShowcaseBuilder.Build(candidates); } - public Task> GetTraitsAsync(CancellationToken ct = default) - { - // Actually this is unused since we mapped it straight to db context in the endpoint, - // but required by interface. - return Task.FromResult>(new List()); - } - public async Task> GetMarketsAsync(int skip = 0, int take = 50, string? platform = null, string? category = null, string? query = null, CancellationToken ct = default) { // NOTE: Currently IMarketRepository.GetActiveAsync doesn't support pagination/filtering. diff --git a/src/Predictalytics.Hosting/PredictalyticsHost.cs b/src/Predictalytics.Hosting/PredictalyticsHost.cs index 41230e5..20cda55 100644 --- a/src/Predictalytics.Hosting/PredictalyticsHost.cs +++ b/src/Predictalytics.Hosting/PredictalyticsHost.cs @@ -17,8 +17,8 @@ namespace Predictalytics.Hosting; /// Plattformneutraler Kern der Anwendung: Lebenszyklus des eingebetteten /// Kestrel-Webservers, der Hintergrund-Worker und der manuellen Wartungsaktionen. /// -/// Enthaelt bewusst keinerlei UI-Bezug — die Hosts (WinForms heute, Avalonia kuenftig, -/// sowie der Headless-Modus) setzen darauf auf. +/// Enthaelt bewusst keinerlei UI-Bezug — die Avalonia-Shell und der +/// Headless-Modus setzen gleichermassen darauf auf. /// /// public sealed class PredictalyticsHost diff --git a/src/Predictalytics.Infrastructure/Predictalytics.Infrastructure.csproj b/src/Predictalytics.Infrastructure/Predictalytics.Infrastructure.csproj index dcf876b..5416116 100644 --- a/src/Predictalytics.Infrastructure/Predictalytics.Infrastructure.csproj +++ b/src/Predictalytics.Infrastructure/Predictalytics.Infrastructure.csproj @@ -14,9 +14,6 @@ - - - diff --git a/src/Predictalytics.Worker/Predictalytics.Worker.csproj b/src/Predictalytics.Worker/Predictalytics.Worker.csproj index 13be172..211b081 100644 --- a/src/Predictalytics.Worker/Predictalytics.Worker.csproj +++ b/src/Predictalytics.Worker/Predictalytics.Worker.csproj @@ -5,10 +5,6 @@ - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - diff --git a/temp_new_design/.thumbnail b/temp_new_design/.thumbnail deleted file mode 100644 index ff3041e..0000000 Binary files a/temp_new_design/.thumbnail and /dev/null differ diff --git a/temp_new_design/API Docs.dc.html b/temp_new_design/API Docs.dc.html deleted file mode 100644 index 719d748..0000000 --- a/temp_new_design/API Docs.dc.html +++ /dev/null @@ -1,173 +0,0 @@ - - - - - - - - - - - - - - - -
- -
-
-
-
{{ brandName }}.
-
- - Get API key -
- -
- - - - -
-

API Reference

-

Programmatic access to every trader and market metric in {{ brandName }}. All endpoints return JSON over HTTPS.

- - -
-

Authentication

-

Pass your API key as a bearer token on every request. Keys are available from your account dashboard after signing up.

-
-
curl https://api.predictalytics.io/v1/markets \
-  -H "Authorization: Bearer YOUR_API_KEY"
-
-
- - -
-

Rate limits

-
- -
-
{{ r.plan }}
-
{{ r.limit }}
-
-
-
-
- - - -
-
- {{ ep.method }} - {{ ep.path }} -
-

{{ ep.desc }}

- -
-
-
Parameters
- -
- {{ p.name }} - {{ p.type }} - {{ p.desc }} -
-
-
-
-
{{ ep.example }}
-
-
-
-
-
-
-
- -
- - - diff --git a/temp_new_design/Landing.dc.html b/temp_new_design/Landing.dc.html deleted file mode 100644 index 162484b..0000000 --- a/temp_new_design/Landing.dc.html +++ /dev/null @@ -1,306 +0,0 @@ - - - - - - - - - - - - - - - -
- - -
-
-
-
{{ brandName }}.
-
- -
-
Log in
-
Sign up
-
-
- - -
-
Live on-chain analytics · Polymarket & beyond
-

See every trader and market before the crowd does

-

Deep trader profiling, wallet clustering, and real-time market analytics for professional prediction market traders.

-
-
Start free
- See features -
- - -
-
-
Yes Price History
- - - - - - - - - - -
-
-
Top Traders
- -
-
-
{{ t.handle }}
-
{{ t.pnl }}
-
-
-
-
-
- - -
-
-
FEATURES
-

Everything you need to read the market

-

Built for quants who need signal, not noise.

-
-
- -
-
-
-
-
{{ f.title }}
-
{{ f.desc }}
-
-
-
-
- - -
-
-
PRICING
-

Simple, usage-based plans

-

Upgrade any time as your call volume grows.

-
-
- -
- -
MOST POPULAR
-
-
{{ p.name }}
-
-
{{ p.price }}
-
{{ p.period }}
-
-
- -
-
- {{ item }} -
-
-
-
{{ p.btnLabel }}
-
-
-
-
- - -
-
-
FAQ
-

Common questions

-
-
- -
-
-
{{ q.question }}
-
+
-
- -
{{ q.answer }}
-
-
-
-
-
- - - - - - -
-
-
-
{{ authTitle }}
-
-
-
- -
- - -
-
-
- - -
-
- - -
-
{{ authSubmitLabel }}
-
- {{ authSwitchPrompt }} {{ authSwitchAction }} -
-
-
-
-
- -
- -
- - - diff --git a/temp_new_design/Prediction Analytics.dc.html b/temp_new_design/Prediction Analytics.dc.html deleted file mode 100644 index e2d72db..0000000 --- a/temp_new_design/Prediction Analytics.dc.html +++ /dev/null @@ -1,875 +0,0 @@ - - - - - - - - - - - - - - - -
- - -
- -
- - - - - -
- - -
-
- -
-
-
-
24H VOL {{ headerVolume }}
-
-
-
-
-
- - -
- - {{ crumb.label }} - - - - -
- - - -
-
-
-

Markets Overview

-
Real-time analytics across all active prediction markets
-
-
- - -
- -
-
{{ stat.label }}
-
{{ stat.value }}
-
{{ stat.delta }}
-
-
-
- -
- -
-
All Markets
- - - - - - - - - - - - - - - - - - - - - -
MarketYes %24hVolumeTraders
-
{{ m.question }}
-
{{ m.category }} · {{ m.statusLabel }}
-
{{ m.yesPriceLabel }}{{ m.changeLabel }}{{ m.volumeLabel }}{{ m.tradersLabel }}
-
- - -
-
Top Traders
-
- -
-
{{ t.initial }}
-
-
{{ t.handle }}
-
{{ t.trait }}
-
-
-
{{ t.pnlLabel }}
-
P&L
-
-
-
-
-
-
-
-
- - - -
-
-
-
-
{{ marketDetail.category }}
-
{{ marketDetail.status }}
-
-

{{ marketDetail.question }}

-
Resolves {{ marketDetail.resolves }}
-
-
-
{{ marketDetail.yesPriceBig }}
-
YES probability
-
-
- -
- -
-
{{ stat.label }}
-
{{ stat.value }}
-
-
-
- -
- -
-
-
Yes Price History
-
-
30D
-
-
- - - - - - - - - - - -
- - -
-
Order Book Depth
-
Asks
- -
-
-
- {{ row.priceLabel }} - {{ row.sizeLabel }} -
-
-
-
-
Bids
- -
-
-
- {{ row.priceLabel }} - {{ row.sizeLabel }} -
-
-
-
-
- -
- -
-
Biggest Holders
- - - - - - - - - - -
{{ h.trader }}{{ h.side }}{{ h.valueLabel }}
-
- - -
-
Top Traders Here
-
- -
-
{{ t.initial }}
-
{{ t.handle }}
-
{{ t.trait }}
-
-
-
-
-
-
-
- - - -
-
-

Trader Search

-
Filter by traits and metric ranges to find the traders you care about
-
- -
- -
-
- -
- -
-
Traits
-
- -
{{ chip.label }}
-
-
-
- -
-
- Win Rate - {{ winRateSlider.minLabel }} – {{ winRateSlider.maxLabel }} -
-
-
-
- - -
-
- - - -
-
- -
-
- Volume - {{ volumeSlider.minLabel }} – {{ volumeSlider.maxLabel }} -
-
-
-
- - -
-
- - - -
-
- -
-
- Total P&L - {{ pnlSlider.minLabel }} – {{ pnlSlider.maxLabel }} -
-
-
-
- - -
-
- - - -
-
- -
Reset filters
-
- - -
-
- Results{{ searchResultsCount }} traders -
- - - - - - - - - - - - - - - - - - - - - -
TraderTraitsWin RateVolumeP&L
-
-
{{ t.initial }}
- {{ t.handle }} -
-
-
- -
{{ chip.label }}
-
-
-
{{ t.winRateLabel }}{{ t.volumeLabel }}{{ t.pnlLabel }}
-
-
-
-
- - - -
-
-
-
{{ traderDetail.initial }}
-
-
-

{{ traderDetail.handle }}

-
{{ traderDetail.wallet }}
-
-
- -
{{ chip.label }}
-
-
-
-
-
-
Member since {{ traderDetail.joined }}
-
{{ traderDetail.activePositionsLabel }} active positions
-
-
- -
- -
-
{{ stat.label }}
-
{{ stat.value }}
-
-
-
- -
- -
-
P&L Over Time
- - - - - - - - - - - -
- - -
-
Connected Wallets
- - -
-
-
{{ w }}
-
-
-
- -
No linked wallets detected.
-
-
-
- - -
-
Positions
- - - - - - - - - - - - - - - - - - - - - - - -
MarketSideSizeEntryCurrentP&L
{{ p.market }}{{ p.side }}{{ p.sizeLabel }}{{ p.entryLabel }}{{ p.currentLabel }}{{ p.pnlLabel }}
-
-
-
- -
-
-
- -
- - - diff --git a/temp_new_design/market-data.js b/temp_new_design/market-data.js deleted file mode 100644 index d8b8472..0000000 --- a/temp_new_design/market-data.js +++ /dev/null @@ -1,290 +0,0 @@ -// Mock data for prediction market analytics prototype - -function genSeries(n, start, vol, drift) { - const pts = [start]; - for (let i = 1; i < n; i++) { - const next = Math.max(2, Math.min(98, pts[i - 1] + (Math.random() - 0.5 + drift) * vol)); - pts.push(Math.round(next * 10) / 10); - } - return pts; -} - -export const MARKETS = [ - { - id: "fed-sep-cut", - question: "Fed cuts rates at September meeting?", - category: "Economics", - status: "Active", - resolves: "Sep 18, 2026", - yesPrice: 71.4, - change24h: 4.2, - volume24h: 2840000, - volumeTotal: 41200000, - liquidity: 6120000, - openInterest: 18400000, - traders: 8340, - yesSeries: genSeries(40, 55, 4, 0.06), - noSeries: null, - orderBook: { - bids: [[71.0, 182000], [70.5, 240000], [70.0, 310000], [69.5, 198000], [69.0, 145000]], - asks: [[71.5, 165000], [72.0, 221000], [72.5, 290000], [73.0, 176000], [73.5, 130000]] - }, - holders: [ - { trader: "0xA13f…9c2", side: "Yes", size: 420000, value: 300000 }, - { trader: "quant_owl", side: "Yes", size: 318000, value: 227000 }, - { trader: "0x77Bd…41a", side: "No", size: 275000, value: 78600 }, - { trader: "resolvr", side: "Yes", size: 210000, value: 150000 }, - { trader: "0x9F02…c88", side: "No", size: 188000, value: 53700 } - ], - topTraders: ["quant_owl", "resolvr", "arb_meridian", "0xA13f…9c2"] - }, - { - id: "btc-150k", - question: "Bitcoin above $150,000 by year end?", - category: "Crypto", - status: "Active", - resolves: "Dec 31, 2026", - yesPrice: 38.2, - change24h: -2.8, - volume24h: 5120000, - volumeTotal: 88900000, - liquidity: 11400000, - openInterest: 34200000, - traders: 21300, - yesSeries: genSeries(40, 45, 5, -0.02), - noSeries: null, - orderBook: { - bids: [[38.0, 410000], [37.5, 380000], [37.0, 512000], [36.5, 290000], [36.0, 210000]], - asks: [[38.5, 390000], [39.0, 460000], [39.5, 330000], [40.0, 280000], [40.5, 190000]] - }, - holders: [ - { trader: "satoshi_fan", side: "Yes", size: 890000, value: 340000 }, - { trader: "0x4Ac1…d02", side: "No", size: 720000, value: 445000 }, - { trader: "bot_delta_9", side: "No", size: 610000, value: 377000 }, - { trader: "arb_meridian", side: "Yes", size: 540000, value: 206000 }, - { trader: "0xE221…7b4", side: "Yes", size: 480000, value: 183000 } - ], - topTraders: ["satoshi_fan", "bot_delta_9", "arb_meridian", "0x4Ac1…d02"] - }, - { - id: "ucl-winner", - question: "Real Madrid win Champions League 2027?", - category: "Sports", - status: "Active", - resolves: "May 30, 2027", - yesPrice: 22.6, - change24h: 1.1, - volume24h: 980000, - volumeTotal: 14300000, - liquidity: 3210000, - openInterest: 7600000, - traders: 5120, - yesSeries: genSeries(40, 20, 3, 0.03), - noSeries: null, - orderBook: { - bids: [[22.0, 92000], [21.5, 110000], [21.0, 88000], [20.5, 64000], [20.0, 51000]], - asks: [[22.5, 87000], [23.0, 101000], [23.5, 76000], [24.0, 55000], [24.5, 40000]] - }, - holders: [ - { trader: "resolvr", side: "Yes", size: 210000, value: 47000 }, - { trader: "0xB901…5e3", side: "No", size: 198000, value: 153000 }, - { trader: "quant_owl", side: "Yes", size: 155000, value: 35000 }, - { trader: "farmer_jo", side: "Yes", size: 121000, value: 27000 } - ], - topTraders: ["resolvr", "quant_owl", "0xB901…5e3"] - }, - { - id: "us-election-28", - question: "Democratic candidate wins 2028 election?", - category: "Politics", - status: "Active", - resolves: "Nov 7, 2028", - yesPrice: 54.8, - change24h: 0.6, - volume24h: 3620000, - volumeTotal: 61500000, - liquidity: 9870000, - openInterest: 28100000, - traders: 14700, - yesSeries: genSeries(40, 50, 3.5, 0.01), - noSeries: null, - orderBook: { - bids: [[54.5, 260000], [54.0, 310000], [53.5, 220000], [53.0, 190000], [52.5, 140000]], - asks: [[55.0, 245000], [55.5, 300000], [56.0, 210000], [56.5, 175000], [57.0, 120000]] - }, - holders: [ - { trader: "0x2Ff8…a10", side: "Yes", size: 610000, value: 334000 }, - { trader: "arb_meridian", side: "No", size: 540000, value: 244000 }, - { trader: "night_owl_88", side: "Yes", size: 410000, value: 224000 }, - { trader: "0xC450…9d1", side: "Yes", size: 380000, value: 208000 } - ], - topTraders: ["0x2Ff8…a10", "arb_meridian", "night_owl_88"] - }, - { - id: "openai-ipo", - question: "OpenAI IPOs before end of 2027?", - category: "Business", - status: "Active", - resolves: "Dec 31, 2027", - yesPrice: 16.9, - change24h: -0.4, - volume24h: 740000, - volumeTotal: 9800000, - liquidity: 2140000, - openInterest: 5300000, - traders: 3980, - yesSeries: genSeries(40, 18, 2.5, -0.01), - noSeries: null, - orderBook: { - bids: [[16.5, 61000], [16.0, 72000], [15.5, 58000], [15.0, 40000], [14.5, 33000]], - asks: [[17.0, 55000], [17.5, 63000], [18.0, 47000], [18.5, 36000], [19.0, 28000]] - }, - holders: [ - { trader: "bot_delta_9", side: "No", size: 310000, value: 258000 }, - { trader: "0x9F02…c88", side: "Yes", size: 190000, value: 32000 }, - { trader: "farmer_jo", side: "No", size: 140000, value: 116000 } - ], - topTraders: ["bot_delta_9", "0x9F02…c88"] - }, - { - id: "fifa-worldcup", - question: "Brazil wins 2026 FIFA World Cup?", - category: "Sports", - status: "Resolved · No", - resolves: "Jul 19, 2026", - yesPrice: 0, - change24h: 0, - volume24h: 0, - volumeTotal: 27600000, - liquidity: 0, - openInterest: 0, - traders: 19200, - yesSeries: genSeries(40, 30, 5, 0.1).map((v,i,a)=> i>34 ? Math.max(0, 30 - (i-34)*6) : v), - noSeries: null, - orderBook: { bids: [], asks: [] }, - holders: [ - { trader: "night_owl_88", side: "No", size: 520000, value: 520000 }, - { trader: "0xC450…9d1", side: "Yes", size: 300000, value: 0 } - ], - topTraders: ["night_owl_88", "0xC450…9d1"] - } -]; - -export const TRADERS = [ - { - id: "quant_owl", - handle: "quant_owl", - wallet: "0x1a4F…88bC", - traits: ["Arbitrage Bot", "High Volume"], - joined: "Mar 2024", - pnlRealized: 184200, - pnlUnrealized: 32100, - winRate: 68.4, - volume: 4820000, - avgPositionSize: 41200, - activePositions: 14, - pnlSeries: genSeries(30, 40, 6, 0.08), - positions: [ - { market: "Fed cuts rates at September meeting?", side: "Yes", size: 318000, entry: 62.1, current: 71.4, pnl: 29580, status: "Open" }, - { market: "Real Madrid win Champions League 2027?", side: "Yes", size: 155000, entry: 18.4, current: 22.6, pnl: 6510, status: "Open" }, - { market: "US Presidential Election 2028", side: "No", size: 96000, entry: 48.2, current: 45.2, pnl: 2880, status: "Open" }, - { market: "Bitcoin above $100k Jan 2026", side: "Yes", size: 210000, entry: 55.0, current: 100, pnl: 94500, status: "Resolved" } - ], - connectedWallets: ["0x88Ac…2f01", "0x5b0D…e410"] - }, - { - id: "bot_delta_9", - handle: "bot_delta_9", - wallet: "0x5C90…14fA", - traits: ["Trading Bot", "Resolution Farming"], - joined: "Jan 2025", - pnlRealized: 61400, - pnlUnrealized: -8200, - winRate: 54.1, - volume: 12400000, - avgPositionSize: 18300, - activePositions: 62, - pnlSeries: genSeries(30, 30, 3, 0.02), - positions: [ - { market: "Bitcoin above $150,000 by year end?", side: "No", size: 610000, entry: 41.0, current: 38.2, pnl: 17080, status: "Open" }, - { market: "OpenAI IPOs before end of 2027?", side: "No", size: 310000, entry: 84.2, current: 83.1, pnl: 3410, status: "Open" }, - { market: "Brazil wins 2026 FIFA World Cup?", side: "No", size: 520000, entry: 71.0, current: 100, pnl: 150800, status: "Resolved" } - ], - connectedWallets: ["0x14fA…C90D", "0x77b2…9e11", "0x0021…aabc"] - }, - { - id: "arb_meridian", - handle: "arb_meridian", - wallet: "0x902D…7Ac1", - traits: ["Arbitrage Bot"], - joined: "Aug 2023", - pnlRealized: 402800, - pnlUnrealized: 51200, - winRate: 71.9, - volume: 22100000, - avgPositionSize: 68400, - activePositions: 9, - pnlSeries: genSeries(30, 60, 5, 0.05), - positions: [ - { market: "Bitcoin above $150,000 by year end?", side: "Yes", size: 540000, entry: 30.5, current: 38.2, pnl: 41580, status: "Open" }, - { market: "Democratic candidate wins 2028 election?", side: "No", size: 540000, entry: 47.0, current: 45.2, pnl: 9720, status: "Open" }, - { market: "Fed cuts rates at September meeting?", side: "Yes", size: 180000, entry: 58.0, current: 71.4, pnl: 24120, status: "Open" } - ], - connectedWallets: [] - }, - { - id: "resolvr", - handle: "resolvr", - wallet: "0xF001…22Cd", - traits: ["Human", "Resolution Farming"], - joined: "Nov 2024", - pnlRealized: 92300, - pnlUnrealized: 12800, - winRate: 59.7, - volume: 6740000, - avgPositionSize: 27600, - activePositions: 22, - pnlSeries: genSeries(30, 35, 4, 0.03), - positions: [ - { market: "Fed cuts rates at September meeting?", side: "Yes", size: 210000, entry: 60.0, current: 71.4, pnl: 23940, status: "Open" }, - { market: "Real Madrid win Champions League 2027?", side: "Yes", size: 210000, entry: 15.2, current: 22.6, pnl: 15540, status: "Open" } - ], - connectedWallets: ["0x22Cd…F001"] - }, - { - id: "night_owl_88", - handle: "night_owl_88", - wallet: "0x3E77…B420", - traits: ["Human", "High Volume"], - pnlRealized: 128900, - pnlUnrealized: 4100, - winRate: 62.2, - volume: 9120000, - avgPositionSize: 35200, - activePositions: 11, - pnlSeries: genSeries(30, 42, 4, 0.04), - positions: [ - { market: "Democratic candidate wins 2028 election?", side: "Yes", size: 410000, entry: 51.0, current: 54.8, pnl: 15580, status: "Open" }, - { market: "Brazil wins 2026 FIFA World Cup?", side: "No", size: 520000, entry: 68.0, current: 100, pnl: 166400, status: "Resolved" } - ], - connectedWallets: [] - }, - { - id: "farmer_jo", - handle: "farmer_jo", - wallet: "0xA210…6Bf0", - traits: ["Human", "Resolution Farming"], - pnlRealized: 21400, - pnlUnrealized: -3100, - winRate: 48.9, - volume: 1840000, - avgPositionSize: 9200, - activePositions: 31, - pnlSeries: genSeries(30, 20, 3, -0.01), - positions: [ - { market: "Real Madrid win Champions League 2027?", side: "Yes", size: 121000, entry: 24.0, current: 22.6, pnl: -1690, status: "Open" }, - { market: "OpenAI IPOs before end of 2027?", side: "No", size: 140000, entry: 80.0, current: 83.1, pnl: -4340, status: "Open" } - ], - connectedWallets: ["0x6Bf0…A210", "0x9021…4Ccb"] - } -]; diff --git a/temp_new_design/support.js b/temp_new_design/support.js deleted file mode 100644 index 6ca00e3..0000000 --- a/temp_new_design/support.js +++ /dev/null @@ -1,1768 +0,0 @@ -// GENERATED from dc-runtime/src/*.ts — do not edit. Rebuild with `cd dc-runtime && bun run build`. -"use strict"; -(() => { - var __defProp = Object.defineProperty; - var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; - var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); - - // src/react.ts - function getReact() { - const R = window.React; - if (!R) throw new Error("dc-runtime: window.React is not available yet"); - return R; - } - function getReactDOM() { - const RD = window.ReactDOM; - if (!RD) throw new Error("dc-runtime: window.ReactDOM is not available yet"); - return RD; - } - var h = ((...args) => getReact().createElement( - ...args - )); - - // src/parse.ts - function parseDcDocument(doc) { - const dc = doc.querySelector("x-dc"); - if (!dc) return null; - const scriptEl = doc.querySelector("script[data-dc-script]"); - const { props, preview } = parseDataProps( - scriptEl?.getAttribute("data-props") ?? null - ); - return { - template: dc.innerHTML, - js: scriptEl ? scriptEl.textContent || "" : "", - props, - preview - }; - } - function parseDcText(src) { - const openMatch = /]*)?>/.exec(src); - if (!openMatch) return null; - const close = src.lastIndexOf(""); - if (close === -1 || close < openMatch.index) return null; - const template = src.slice(openMatch.index + openMatch[0].length, close); - const doc = new DOMParser().parseFromString(src, "text/html"); - const scriptEl = doc.querySelector("script[data-dc-script]"); - const { props, preview } = parseDataProps( - scriptEl?.getAttribute("data-props") ?? null - ); - return { - template, - js: scriptEl ? scriptEl.textContent || "" : "", - props, - preview - }; - } - function parseDataProps(raw) { - if (!raw) return { props: null, preview: null }; - let parsed; - try { - parsed = JSON.parse(raw); - } catch { - return { props: null, preview: null }; - } - if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) { - return { props: null, preview: null }; - } - const obj = parsed; - const preview = obj.$preview && typeof obj.$preview === "object" ? obj.$preview : null; - const rest = {}; - for (const k of Object.keys(obj)) { - if (k[0] !== "$") rest[k] = obj[k]; - } - return { props: Object.keys(rest).length ? rest : null, preview }; - } - function dcNameFromPath(pathname) { - let p = pathname || ""; - try { - p = decodeURIComponent(p); - } catch { - } - const base = p.split("/").pop() || "Root"; - return base.replace(/\.dc\.html$/, "").replace(/\.html?$/, "") || "Root"; - } - - // src/boot.ts - var BASE_CSS = ` - .sc-placeholder{background:color-mix(in srgb,currentColor 8%,transparent); - border:1px solid color-mix(in srgb,currentColor 50%,transparent); - border-radius:2px;box-sizing:border-box;overflow:hidden} - @keyframes sc-shine{0%{background-position:100% 50%}100%{background-position:0% 50%}} - html.sc-dc-streaming .sc-placeholder, - html.sc-dc-streaming .sc-interp.sc-missing{position:relative; - background:color-mix(in srgb,currentColor 5%,transparent); - border-color:transparent} - html.sc-dc-streaming .sc-placeholder::before, - html.sc-dc-streaming .sc-interp.sc-missing::before{content:''; - position:absolute;inset:0;pointer-events:none; - background:linear-gradient(90deg,rgba(217,119,87,0) 25%,rgba(247,225,211,.95) 37%,rgba(217,119,87,0) 63%); - background-size:400% 100%;animation:sc-shine 1.4s ease infinite} - html.sc-dc-streaming .sc-placeholder:nth-child(n+9 of .sc-placeholder)::before, - html.sc-dc-streaming .sc-interp.sc-missing:nth-child(n+9 of .sc-interp.sc-missing)::before{animation:none; - background:color-mix(in srgb,currentColor 8%,transparent)} - .sc-placeholder-error{padding:4px 8px;font:11px/1.4 ui-monospace,monospace; - color:color-mix(in srgb,currentColor 70%,transparent);word-break:break-word} - .sc-interp.sc-missing{display:inline-block;width:2em;height:1em;overflow:hidden; - vertical-align:text-bottom;background:rgba(255,255,255,.3);border:1px solid rgba(0,0,0,.5); - border-radius:2px;box-sizing:border-box;color:transparent; - user-select:none} - .sc-interp.sc-unresolved{font-family:ui-monospace,monospace;font-size:.85em; - color:color-mix(in srgb,currentColor 50%,transparent); - background:color-mix(in srgb,currentColor 10%,transparent);border-radius:3px; - padding:0 3px} - .sc-host.sc-has-error{position:relative} - .sc-logic-error{position:absolute;top:8px;left:8px;z-index:2147483647;max-width:60ch; - padding:6px 10px;background:#b00020;color:#fff;font:12px/1.4 ui-monospace,monospace; - border-radius:4px;white-space:pre-wrap;pointer-events:none} - /* Mirrors PRINT_BASELINE_CSS in apps/web deck-stage-export.ts \u2014 keep both - in sync until dc-runtime regains a build step. */ - @media print { - @page { margin: 0.5cm; } - figure, table { break-inside: avoid; } - #dc-root, #dc-root > .sc-host { height: auto; } - *, *::before, *::after { - print-color-adjust: exact; -webkit-print-color-adjust: exact; - backdrop-filter: none !important; -webkit-backdrop-filter: none !important; - animation-delay: -99s !important; animation-duration: .001s !important; - animation-iteration-count: 1 !important; animation-fill-mode: both !important; - animation-play-state: running !important; transition-duration: 0s !important; - } - } - `; - var FULL_PAGE_CSS = "html,body{height:100%;margin:0}#dc-root,#dc-root>.sc-host{height:100%}"; - function rootNameForDocument(doc, loc) { - let bootPath = loc.pathname || ""; - if (!/\.dc\.html?$/i.test(safeDecode(bootPath))) { - try { - bootPath = new URL(doc.baseURI || "/").pathname; - } catch { - } - } - return dcNameFromPath(bootPath); - } - function safeDecode(s) { - try { - return decodeURIComponent(s); - } catch { - return s; - } - } - function boot(runtime, doc = document) { - const parsed = parseDcDocument(doc); - if (!parsed) return null; - const React = getReact(); - const rootName = rootNameForDocument(doc, location); - runtime.markFetched(rootName); - runtime.setRootName(rootName); - runtime.adoptParsed(rootName, parsed); - if (!window.__resources) { - fetch(location.href).then((res) => res.ok ? res.text() : "").then((t) => { - const raw = t ? parseDcText(t) : null; - if (raw?.template) runtime.updateHtml(rootName, raw.template); - }).catch(() => { - }); - } - const dc = doc.querySelector("x-dc"); - const hostEl = doc.createElement("div"); - hostEl.id = "dc-root"; - dc.replaceWith(hostEl); - if (!parsed.preview) { - const s = doc.createElement("style"); - s.textContent = FULL_PAGE_CSS; - doc.head.appendChild(s); - } - const Root = runtime.getDC(rootName); - const entry = runtime.registry.get(rootName); - function StandaloneRoot() { - const [, setTick] = React.useState(0); - React.useEffect(() => { - const sub = () => setTick((n) => n + 1); - entry.subs.add(sub); - return () => { - entry.subs.delete(sub); - }; - }, []); - const defaults = React.useMemo(() => { - const d = {}; - for (const k in entry.propsMeta || {}) { - const v = entry.propsMeta?.[k]?.default; - if (v !== void 0) d[k] = v; - } - return d; - }, [entry.propsMeta]); - return h(Root, { ...defaults, ...entry.propOverrides || {} }); - } - const ReactDOM = getReactDOM(); - if (ReactDOM.createRoot) - ReactDOM.createRoot(hostEl).render(h(StandaloneRoot)); - else ReactDOM.render(h(StandaloneRoot), hostEl); - return rootName; - } - - // src/expr.ts - var IDENT_RE = /^[A-Za-z_$][A-Za-z0-9_$]*/; - var NUMBER_RE = /^-?\d+(\.\d+)?$/; - function resolve(vals, src) { - const expr = String(src).trim(); - if (!expr) return void 0; - if (expr[0] === "(" && expr[expr.length - 1] === ")" && parensWrapWhole(expr)) { - return resolve(vals, expr.slice(1, -1)); - } - const eq = findTopLevelEquality(expr); - if (eq) { - const lv = resolve(vals, expr.slice(0, eq.index)); - const rv = resolve(vals, expr.slice(eq.index + eq.op.length)); - switch (eq.op) { - case "===": - return lv === rv; - case "!==": - return lv !== rv; - case "==": - return lv == rv; - default: - return lv != rv; - } - } - if (expr[0] === "!") return !resolve(vals, expr.slice(1)); - if (expr === "true") return true; - if (expr === "false") return false; - if (expr === "null") return null; - if (expr === "undefined") return void 0; - if (NUMBER_RE.test(expr)) return Number(expr); - if (expr.length >= 2 && (expr[0] === '"' || expr[0] === "'") && expr[expr.length - 1] === expr[0]) { - return expr.slice(1, -1); - } - return resolvePath(vals, expr); - } - function parensWrapWhole(expr) { - let depth = 0; - for (let i = 0; i < expr.length - 1; i++) { - if (expr[i] === "(") depth++; - else if (expr[i] === ")") { - depth--; - if (depth === 0) return false; - } - } - return true; - } - function findTopLevelEquality(expr) { - let depth = 0; - for (let i = 0; i < expr.length; i++) { - const c = expr[i]; - if (c === "[" || c === "(") depth++; - else if (c === "]" || c === ")") depth--; - else if (depth === 0 && (c === "=" || c === "!") && expr[i + 1] === "=") { - if (i > 0 && (expr[i - 1] === "=" || expr[i - 1] === "!")) continue; - if (!expr.slice(0, i).trim()) continue; - const op = expr[i + 2] === "=" ? c + "==" : c + "="; - return { index: i, op }; - } - } - return null; - } - function resolvePath(vals, expr) { - const head = expr.match(IDENT_RE); - if (!head) return void 0; - let cur = vals == null ? void 0 : vals[head[0]]; - let i = head[0].length; - while (i < expr.length) { - if (expr[i] === ".") { - const m = expr.slice(i + 1).match(IDENT_RE) || expr.slice(i + 1).match(/^\d+/); - if (!m) return void 0; - cur = cur == null ? void 0 : cur[m[0]]; - i += 1 + m[0].length; - } else if (expr[i] === "[") { - let depth = 1; - let j = i + 1; - while (j < expr.length && depth > 0) { - if (expr[j] === "[") depth++; - else if (expr[j] === "]") { - depth--; - if (depth === 0) break; - } - j++; - } - if (depth !== 0) return void 0; - const key = resolve(vals, expr.slice(i + 1, j)); - cur = cur == null ? void 0 : cur[key]; - i = j + 1; - } else { - return void 0; - } - } - return cur; - } - - // src/encode.ts - var CAMEL_ATTR = "sc-camel-"; - var INLINE_TEXT_TAGS = new Set( - "a abbr b bdi bdo br cite code del dfn em i ins kbd mark q s samp small span strike strong sub sup u var wbr".split( - " " - ) - ); - var RAW_WRAP = { - select: "sc-raw-select", - table: "sc-raw-table", - tbody: "sc-raw-tbody", - thead: "sc-raw-thead", - tfoot: "sc-raw-tfoot", - tr: "sc-raw-tr", - td: "sc-raw-td", - th: "sc-raw-th", - caption: "sc-raw-caption" - }; - var RAW_UNWRAP = Object.fromEntries( - Object.entries(RAW_WRAP).map(([k, v]) => [v, k]) - ); - var EVENT_MAP = { - onclick: "onClick", - onchange: "onChange", - oninput: "onInput", - onsubmit: "onSubmit", - onkeydown: "onKeyDown", - onkeyup: "onKeyUp", - onkeypress: "onKeyPress", - onmousedown: "onMouseDown", - onmouseup: "onMouseUp", - onmouseenter: "onMouseEnter", - onmouseleave: "onMouseLeave", - onfocus: "onFocus", - onblur: "onBlur", - ondoubleclick: "onDoubleClick", - oncontextmenu: "onContextMenu", - onmousemove: "onMouseMove", - onmouseover: "onMouseOver", - onmouseout: "onMouseOut", - onpointerdown: "onPointerDown", - onpointerup: "onPointerUp", - onpointermove: "onPointerMove", - onpointerenter: "onPointerEnter", - onpointerleave: "onPointerLeave", - onpointercancel: "onPointerCancel", - onpointerover: "onPointerOver", - onpointerout: "onPointerOut", - ongotpointercapture: "onGotPointerCapture", - onlostpointercapture: "onLostPointerCapture", - ontouchstart: "onTouchStart", - ontouchend: "onTouchEnd", - ontouchmove: "onTouchMove", - ontouchcancel: "onTouchCancel", - ondragstart: "onDragStart", - ondragend: "onDragEnd", - ondragenter: "onDragEnter", - ondragleave: "onDragLeave", - ondragover: "onDragOver", - onanimationstart: "onAnimationStart", - onanimationend: "onAnimationEnd", - onanimationiteration: "onAnimationIteration", - ontransitionend: "onTransitionEnd" - }; - var ATTRS = `(?:[^>"']|"[^"]*"|'[^']*')*`; - var IMPORT_SELF_CLOSE_RE = new RegExp( - "<(x-import|dc-import)(" + ATTRS + ")/>", - "gi" - ); - var CAMEL_ATTR_RE = /(\s)([a-z]+[A-Z][A-Za-z0-9]*)(\s*=)/g; - function encodeCamelAttrs(html) { - return html.replace( - CAMEL_ATTR_RE, - (_, sp, name, eq) => sp + CAMEL_ATTR + name.replace(/[A-Z]/g, (c) => "-" + c.toLowerCase()) + eq - ); - } - function encodeCase(html) { - html = html.replace( - IMPORT_SELF_CLOSE_RE, - (_, t, a) => "<" + t + a + ">" - ); - html = html.replace(/)/gi, "/gi, ""); - html = encodeCamelAttrs(html); - for (const [real, alias] of Object.entries(RAW_WRAP)) { - html = html.replace( - new RegExp("(])", "gi"), - "$1" + alias - ); - } - return html; - } - function kebabToCamel(s) { - return s.replace(/-([a-z])/g, (_, c) => c.toUpperCase()); - } - function cssToObj(css) { - const o = {}; - for (const decl of css.split(";")) { - const i = decl.indexOf(":"); - if (i < 0) continue; - const prop = decl.slice(0, i).trim(); - o[prop.startsWith("--") ? prop : kebabToCamel(prop)] = decl.slice(i + 1).trim(); - } - return o; - } - function compileAttr(raw) { - const whole = raw.match(/^\s*\{\{([\s\S]+?)\}\}\s*$/); - if (whole) { - const path = whole[1]; - return (vals) => resolve(vals, path); - } - if (raw.includes("{{")) { - const parts = raw.split(/\{\{([\s\S]+?)\}\}/g); - return (vals) => parts.map((s, i) => i & 1 ? resolve(vals, s) ?? "" : s).join(""); - } - return () => raw; - } - - // src/compile.ts - function collectProps(node, kind, host) { - const propGetters = []; - const pseudoClasses = []; - let hintSize = null; - for (const { name, value } of [...node.attributes]) { - if (name === "sc-name" || name === "data-dc-tpl") continue; - let key = name; - if (key.startsWith(CAMEL_ATTR)) - key = kebabToCamel(key.slice(CAMEL_ATTR.length)); - if (key === "hint-size") { - hintSize = value; - continue; - } - if (key.startsWith("style-")) { - pseudoClasses.push(host.pseudoClass(key.slice(6), value)); - continue; - } - if (kind !== "dom") { - if (key.includes("-") && !(kind === "x-import" && (key.startsWith("aria-") || key.startsWith("data-")))) - key = kebabToCamel(key); - } else { - if (key === "class") key = "className"; - else if (key === "for") key = "htmlFor"; - else if (key.startsWith("on")) - key = EVENT_MAP[key] || "on" + key[2].toUpperCase() + key.slice(3); - } - propGetters.push([key, compileAttr(value)]); - } - return { propGetters, pseudoClasses, hintSize }; - } - var HOST_STYLE_PROPS = /* @__PURE__ */ new Set([ - "position", - "left", - "right", - "top", - "bottom", - "inset", - "width", - "height", - "z-index", - "transform" - ]); - function hostPositionStyle(style) { - const all = typeof style === "string" ? cssToObj(style) : style != null && typeof style === "object" ? style : null; - if (!all) return void 0; - const out = {}; - for (const [k, v] of Object.entries(all)) { - const kebab = k.replace(/[A-Z]/g, (c) => "-" + c.toLowerCase()); - if (HOST_STYLE_PROPS.has(kebab)) out[k] = v; - } - return Object.keys(out).length ? out : void 0; - } - function compileTemplate(html, host) { - const tpl = document.createElement("template"); - //! nosemgrep: direct-inner-html-assignment - tpl.innerHTML = encodeCase(html); - let tplN = 0; - (function stamp(node) { - if (node.nodeType === Node.ELEMENT_NODE) { - node.setAttribute("data-dc-tpl", String(tplN++)); - } - for (const c of node.childNodes) stamp(c); - })(tpl.content); - const builders = walkChildren(tpl.content, host); - const render = ((vals, ctx) => builders.map((b, i) => b(vals || {}, ctx, i))); - render.__annotated = tpl.innerHTML; - return render; - } - function walkChildren(node, host) { - return [...node.childNodes].map((c) => walk(c, host)).filter((b) => b != null); - } - function walk(node, host) { - if (node.nodeType === Node.TEXT_NODE) return walkText(node); - if (node.nodeType !== Node.ELEMENT_NODE) return null; - const el = node; - const tag = el.tagName.toLowerCase(); - if (tag === "sc-for") return walkFor(el, host); - if (tag === "sc-if") return walkIf(el, host); - if (tag === "x-import") return walkXImport(el, host); - if (tag === "sc-helmet") return host.helmet(el); - if (tag === "dc-import") return walkComponent(el, host); - return walkElement(el, host); - } - var warnedHoles = /* @__PURE__ */ new Set(); - function warnUnresolved(ctx, what) { - const key = (ctx?.__name || "?") + "\0" + what; - if (warnedHoles.has(key)) return; - warnedHoles.add(key); - console.warn("[dc-runtime] " + (ctx?.__name || "template") + ": " + what); - } - function walkText(node) { - const txt = node.nodeValue ?? ""; - if (!txt.includes("{{")) { - if (!txt.trim() && !txt.includes(" ")) return null; - return () => txt; - } - const parts = txt.split(/\{\{([\s\S]+?)\}\}/g); - return (vals, ctx, key) => h( - getReact().Fragment, - { key }, - ...parts.map((p, i) => { - if (!(i & 1)) return p; - const v = resolve(vals, p); - if (v === void 0) { - if (!ctx?.__streamingNow) { - if (document.body?.hasAttribute("data-dc-editor-on")) { - return h( - "span", - { key: i, className: "sc-interp sc-unresolved" }, - "{{ " + p.trim() + " }}" - ); - } - warnUnresolved( - ctx, - "{{ " + p.trim() + " }} never resolved \u2014 rendered as empty" - ); - return null; - } - return h( - "span", - { key: i, className: "sc-interp sc-missing" }, - p.trim() - ); - } - if (getReact().isValidElement(v) || Array.isArray(v)) { - return h(getReact().Fragment, { key: i }, v); - } - if (v === null || typeof v === "boolean") return null; - return h("span", { key: i, className: "sc-interp" }, String(v)); - }) - ); - } - function walkFor(el, host) { - const listGet = compileAttr(el.getAttribute("list") || ""); - const asName = el.getAttribute("as") || "item"; - const hintN = parseInt(el.getAttribute("hint-placeholder-count") || "0", 10); - const kids = walkChildren(el, host); - const listSrc = el.getAttribute("list") || ""; - return (vals, ctx, key) => { - let list = listGet(vals); - if (!Array.isArray(list)) { - if (!ctx?.__streamingNow) { - if (list !== void 0 && list !== null) { - warnUnresolved( - ctx, - 'sc-for list="' + listSrc + '" is not an array (' + typeof list + ")" - ); - } - list = []; - } else { - list = hintN > 0 ? Array(hintN).fill(void 0) : []; - } - } - return h( - getReact().Fragment, - { key }, - list.map((item, i) => { - const sub = { ...vals, [asName]: item, $index: i }; - return h( - getReact().Fragment, - { key: i }, - kids.map((b, j) => b(sub, ctx, j)) - ); - }) - ); - }; - } - function walkIf(el, host) { - const valGet = compileAttr(el.getAttribute("value") || ""); - const hintRaw = el.getAttribute("hint-placeholder-val"); - const hintGet = hintRaw != null ? compileAttr(hintRaw) : null; - const kids = walkChildren(el, host); - return (vals, ctx, key) => { - let v = valGet(vals); - if (v === void 0 && hintGet && ctx?.__streamingNow) v = hintGet(vals); - return v ? h( - getReact().Fragment, - { key }, - kids.map((b, j) => b(vals, ctx, j)) - ) : null; - }; - } - function walkComponent(el, host) { - const name = el.getAttribute("name") || el.getAttribute("component") || ""; - el.removeAttribute("name"); - el.removeAttribute("component"); - const tplId = el.getAttribute("data-dc-tpl"); - const styleRaw = el.getAttribute("style"); - el.removeAttribute("style"); - const styleGet = styleRaw != null ? compileAttr(styleRaw) : null; - const { propGetters, hintSize } = collectProps(el, "dc-import", host); - const kids = walkChildren(el, host); - return (vals, ctx, key) => { - const props = { - key, - __hintSize: hintSize, - __tplId: tplId, - __hostStyle: styleGet ? hostPositionStyle(styleGet(vals)) : void 0 - }; - for (const [k, g] of propGetters) { - const v = g(vals); - if (k === "dcProps") { - if (v && typeof v === "object") Object.assign(props, v); - continue; - } - props[k] = v; - } - if (kids.length) props.children = kids.map((b, j) => b(vals, ctx, j)); - return h(host.component(name), props); - }; - } - function walkXImport(el, host) { - const globalNameGet = compileAttr( - el.getAttribute("component-from-global-scope") || "" - ); - const exportNameGet = compileAttr( - el.getAttribute("component") || el.getAttribute("name") || "" - ); - const fromRaw = el.getAttribute("from") || (el.getAttribute("component-from-global-scope") ? "" : el.getAttribute("src") || el.getAttribute("import") || ""); - const urls = fromRaw.trim() ? fromRaw.trim().split(/\s+/) : []; - const url = urls.length ? urls[urls.length - 1] : ""; - const kindOf = (u) => /\.(jsx|tsx)(\?|#|$)/i.test(u) ? "jsx" : "js"; - const tplId = el.getAttribute("data-dc-tpl"); - const styleRaw = el.getAttribute("style"); - el.removeAttribute("style"); - const styleGet = styleRaw != null ? compileAttr(styleRaw) : null; - const wrap = tplId != null || styleGet != null; - const { propGetters, hintSize } = collectProps(el, "x-import", host); - const hasContent = el.children.length > 0 || !!(el.textContent || "").trim(); - const kids = hasContent ? walkChildren(el, host) : []; - const urlBindable = fromRaw.includes("{{"); - if (urls.length && !urlBindable) { - let prev; - for (const u of urls) prev = host.loadExternal(kindOf(u), u, prev); - } - const evalName = (g, vals) => { - const v = g(vals); - const s = v == null ? "" : String(v); - return s.includes("{{") ? "" : s; - }; - return (vals, ctx, key) => { - const globalName = evalName(globalNameGet, vals); - const name = globalName || evalName(exportNameGet, vals); - const C = !name || urlBindable ? null : globalName ? host.resolveExternalGlobal(url, globalName) : host.resolveExternal(url, name); - const hostStyle = styleGet ? hostPositionStyle(styleGet(vals)) : void 0; - const wrapper = wrap ? { - key, - className: "sc-host-x", - "data-dc-tpl": tplId, - style: hostStyle || { display: "contents" } - } : null; - if (!C) { - const error = urlBindable ? "x-import `from` cannot contain {{ \u2026 }} \u2014 module URLs are resolved at parse time; use a literal URL" : host.resolveExternalError(url, name); - const ph = host.placeholder({ - key: wrapper ? void 0 : key, - name, - hintSize, - error - }); - return wrapper ? h("div", wrapper, ph) : ph; - } - const props = wrapper ? {} : { key }; - let unresolvedHole = false; - for (const [k, g] of propGetters) { - if (k === "component" || k === "componentFromGlobalScope" || k === "from") { - continue; - } - const v = g(vals); - if (v === void 0) unresolvedHole = true; - if (k === "dcProps") { - if (v && typeof v === "object") Object.assign(props, v); - continue; - } - props[k] = v; - } - if (unresolvedHole && ctx?.__htmlStreamingNow) { - const ph = host.placeholder({ - key: wrapper ? void 0 : key, - name, - hintSize, - error: null - }); - return wrapper ? h("div", wrapper, ph) : ph; - } - if (kids.length) props.children = kids.map((b, j) => b(vals, ctx, j)); - return wrapper ? h("div", wrapper, h(C, props)) : h(C, props); - }; - } - function contentKey(el) { - const clone = el.cloneNode(true); - for (const d of clone.querySelectorAll("*")) { - while (d.attributes.length) d.removeAttribute(d.attributes[0].name); - } - const s = clone.innerHTML; - let h2 = 5381; - for (let i = 0; i < s.length; i++) h2 = (h2 << 5) + h2 + s.charCodeAt(i) | 0; - return s.length + "." + (h2 >>> 0).toString(36); - } - var NEVER_CONTENT_KEYED = new Set( - "script style textarea option title select canvas iframe video audio".split( - " " - ) - ); - var NOT_INLINE_SELECTOR = ":not(" + [...INLINE_TEXT_TAGS].join(",") + ")"; - function walkElement(el, host) { - const realTag = RAW_UNWRAP[el.localName] || el.localName; - const tplId = el.getAttribute("data-dc-tpl"); - const inlineOnly = el.childNodes.length > 0 && !NEVER_CONTENT_KEYED.has(realTag) && el.querySelector(NOT_INLINE_SELECTOR) === null; - const keySuffix = inlineOnly ? "|" + contentKey(el) : ""; - const { propGetters, pseudoClasses } = collectProps(el, "dom", host); - const kids = walkChildren(el, host); - return (vals, ctx, key) => { - const props = { - key: key + keySuffix, - "data-dc-tpl": tplId - }; - for (const [k, g] of propGetters) { - let v = g(vals); - if (k === "style" && typeof v === "string") v = cssToObj(v); - if ((k === "value" || k === "checked") && v === void 0) { - v = k === "checked" ? false : ""; - } - props[k] = v; - } - if (pseudoClasses.length) { - props.className = [props.className, ...pseudoClasses].filter(Boolean).join(" "); - } - return h(realTag, props, ...kids.map((b, j) => b(vals, ctx, j))); - }; - } - - // src/logic.ts - var StreamableLogic = class { - constructor(props) { - __publicField(this, "props"); - __publicField(this, "state", {}); - /** Back-pointer to the wrapper component, installed after construction. */ - __publicField(this, "__host"); - this.props = props || {}; - } - setState(update, cb) { - this.__host && this.__host.__setLogicState(update, cb); - } - forceUpdate() { - this.__host && this.__host.forceUpdate(); - } - componentDidMount() { - } - componentDidUpdate(_prevProps) { - } - componentWillUnmount() { - } - /** The flat object the template renders against (merged over props). */ - renderVals() { - return {}; - } - }; - function evalDcLogic(src) { - //! nosemgrep: eval-and-function-constructor - const fn = new Function( - "DCLogic", - "StreamableLogic", - "React", - src + '\n;return (typeof Component!=="undefined"&&Component)||undefined;' - ); - return fn(StreamableLogic, StreamableLogic, getReact()); - } - - // src/component.ts - function shallowEqual(a, b) { - if (!b) return false; - const ak = Object.keys(a).filter((k) => k !== "children"); - const bk = Object.keys(b).filter((k) => k !== "children"); - if (ak.length !== bk.length) return false; - for (const k of ak) if (a[k] !== b[k]) return false; - return true; - } - function Placeholder({ - name, - hintSize, - streaming, - error - }) { - const [w, hgt] = (hintSize || "100%,60px").split(","); - return h( - "div", - { - className: "sc-placeholder" + (streaming ? " sc-streaming" : ""), - style: { width: w.trim(), height: hgt && hgt.trim() }, - title: name - }, - error ? h( - "div", - { className: "sc-placeholder-error" }, - (name ? name + ": " : "") + error - ) : null - ); - } - function hintToMin(hint) { - if (!hint) return void 0; - const [w, hgt] = hint.split(","); - return { minWidth: w.trim(), minHeight: hgt && hgt.trim() }; - } - function createComponentFactory(registry, ensureFetched) { - const React = getReact(); - const AncestorContext = React.createContext([]); - class StreamableComponent extends React.Component { - constructor(props) { - super(props); - __publicField(this, "__name"); - __publicField(this, "__sub"); - __publicField(this, "__needsDidMount", false); - /** Snapshot of the registry's streaming flags taken at render time — - * builders read it off the RenderCtx (this) to pick placeholder vs - * render-nothing for unresolved values. */ - __publicField(this, "__streamingNow", false); - __publicField(this, "__htmlStreamingNow", false); - /** When a construct throws, remember the (class, registry.ver, props) - * triple so render-time reconcile doesn't re-attempt it on every parent - * re-render. A registry bump (new class, template, external module - * resolving via bumpAll) changes `ver` and breaks the memo so an - * env-dependent constructor can self-heal. */ - __publicField(this, "__failedLogic", null); - __publicField(this, "__failedUserProps", null); - __publicField(this, "__failedVer", -1); - /** Per-instance constructor error — kept here (not on the registry entry) - * so one instance's successful construct can't hide a sibling's failure, - * and a construct can never wipe an eval error `updateJs` recorded on - * `r.logicError`. */ - __publicField(this, "__ctorError", null); - __publicField(this, "logic"); - this.__name = props.__name; - this.state = { __v: 0, __err: null }; - this.__sub = () => { - if (this.state.__err) this.setState({ __err: null }); - this.forceUpdate(); - }; - this.__makeLogic(registry.get(this.__name).Logic, null); - ensureFetched(this.__name); - } - /** Error-boundary hook: a render crash anywhere in this DC's subtree - * (its own template, an x-import'd component, a child DC without its - * own deeper boundary) lands here instead of unmounting the page. */ - static getDerivedStateFromError(e) { - return { __err: e instanceof Error && e.message ? e.message : String(e) }; - } - componentDidCatch(e, info) { - console.error( - "[dc-runtime] render error in <" + this.__name + ">:", - e, - info?.componentStack || "" - ); - } - /** Instantiate the logic class (or the no-op base) and adopt `prevState` - * over its initial state — used both at mount and on hot-swap. */ - __makeLogic(Logic, prevState) { - const L = Logic || StreamableLogic; - try { - this.logic = new L(this.__userProps()); - this.__failedLogic = null; - this.__failedUserProps = null; - this.__ctorError = null; - } catch (e) { - console.error(e); - this.__failedLogic = Logic; - this.__failedUserProps = this.__userProps(); - this.__failedVer = registry.get(this.__name).ver; - this.__ctorError = this.__name + ": " + (e instanceof Error && e.message ? e.message : String(e)); - this.logic = new StreamableLogic( - this.__userProps() - ); - } - this.logic.__host = this; - if (prevState) - this.logic.state = { ...this.logic.state || {}, ...prevState }; - } - /** The props the author's logic + template see — internal __-prefixed - * wiring stripped. */ - __userProps() { - const { __name, __hintSize, __tplId, __hostStyle, ...rest } = this.props; - return rest; - } - __setLogicState(update, cb) { - const prev = this.logic.state; - const patch = typeof update === "function" ? update(prev) : update; - this.logic.state = { ...prev, ...patch }; - this.setState((s) => ({ __v: s.__v + 1 }), cb); - } - /** Swap the logic instance when the registry's Logic class changed - * (streaming completion, hot reload). State carries over; didMount - * re-fires after the swap commits so refs exist. */ - __reconcileLogic() { - const r = registry.get(this.__name); - const Next = r.Logic; - const Cur = this.logic.constructor; - if (Next === Cur || !Next && Cur === StreamableLogic || Next === this.__failedLogic && r.ver === this.__failedVer && shallowEqual(this.__userProps(), this.__failedUserProps)) { - return; - } - if (!this.__needsDidMount) { - try { - this.logic.componentWillUnmount(); - } catch (e) { - console.error(e); - } - } - this.__makeLogic(Next, this.logic.state); - this.__needsDidMount = true; - } - componentDidMount() { - registry.get(this.__name).subs.add(this.__sub); - try { - this.logic.componentDidMount(); - } catch (e) { - console.error(e); - } - } - componentDidUpdate(prevProps) { - this.logic.props = this.__userProps(); - if (this.__needsDidMount) { - if (this.state.__err || !registry.get(this.__name).tpl) return; - this.__needsDidMount = false; - try { - this.logic.componentDidMount(); - } catch (e) { - console.error(e); - } - } else { - try { - this.logic.componentDidUpdate(prevProps); - } catch (e) { - console.error(e); - } - } - } - componentWillUnmount() { - registry.get(this.__name).subs.delete(this.__sub); - if (!this.__needsDidMount) { - try { - this.logic.componentWillUnmount(); - } catch (e) { - console.error(e); - } - } - } - render() { - const r = registry.get(this.__name); - const cls = "sc-host" + (r.htmlStreaming ? " sc-streaming-html" : "") + (r.jsStreaming ? " sc-streaming-js" : ""); - const hintStyle = r.htmlStreaming ? hintToMin(this.props.__hintSize) : void 0; - const hostStyle = this.props.__hostStyle || hintStyle ? { ...hintStyle || {}, ...this.props.__hostStyle || {} } : void 0; - const hostBase = { - className: cls, - style: hostStyle, - "data-sc-name": this.__name, - "data-dc-tpl": this.props.__tplId - }; - const chain = Array.isArray(this.context) ? this.context : []; - if (chain.includes(this.__name)) { - const cycle = [ - ...chain.slice(chain.indexOf(this.__name)), - this.__name - ].join(" \u2192 "); - return h( - "div", - { ...hostBase, className: cls + " sc-has-error" }, - h(Placeholder, { - name: this.__name, - hintSize: this.props.__hintSize, - error: "circular import: " + cycle - }) - ); - } - if (this.state.__err) { - return h( - "div", - { ...hostBase, className: cls + " sc-has-error" }, - h( - "div", - { className: "sc-logic-error", "data-omelette-chrome": "" }, - this.__name + ": " + this.state.__err - ), - h(Placeholder, { - name: this.__name, - hintSize: this.props.__hintSize, - error: this.state.__err - }) - ); - } - this.__reconcileLogic(); - if (!r.tpl) { - return h( - "div", - hostBase, - h(Placeholder, { name: this.__name, hintSize: this.props.__hintSize }) - ); - } - const userProps = this.__userProps(); - this.logic.props = userProps; - let vals = userProps; - let renderErr = r.logicError || this.__ctorError; - try { - vals = { ...userProps, ...this.logic.renderVals() || {} }; - } catch (e) { - console.error(e); - renderErr = this.__name + ".renderVals(): " + (e instanceof Error && e.message ? e.message : String(e)); - } - this.__streamingNow = !!(r.htmlStreaming || r.jsStreaming); - this.__htmlStreamingNow = !!r.htmlStreaming; - return h( - "div", - { ...hostBase, className: cls + (renderErr ? " sc-has-error" : "") }, - renderErr && h( - "div", - { className: "sc-logic-error", "data-omelette-chrome": "" }, - renderErr - ), - h( - AncestorContext.Provider, - { value: [...chain, this.__name] }, - r.tpl(vals, this) - ) - ); - } - } - __publicField(StreamableComponent, "contextType", AncestorContext); - const named = /* @__PURE__ */ new Map(); - function getDC(name) { - const hit = named.get(name); - if (hit) return hit; - function Dispatcher(p) { - const [, setTick] = React.useState(0); - React.useEffect(() => { - const sub = () => setTick((n) => n + 1); - registry.get(name).subs.add(sub); - return () => { - registry.get(name).subs.delete(sub); - }; - }, []); - ensureFetched(name); - return h(StreamableComponent, { ...p, __name: name }); - } - Dispatcher.displayName = name; - named.set(name, Dispatcher); - return Dispatcher; - } - return { - getDC, - StreamableComponent - }; - } - - // src/bundled.ts - function bundledBlob(url) { - const blobs = window.__resourceBlobs; - const b = blobs ? blobs[url.split("#")[0]] : void 0; - return b instanceof Blob ? b : null; - } - - // src/cdn.ts - var REACT_URL = "https://unpkg.com/react@18.3.1/umd/react.production.min.js"; - var REACT_SRI = "sha384-DGyLxAyjq0f9SPpVevD6IgztCFlnMF6oW/XQGmfe+IsZ8TqEiDrcHkMLKI6fiB/Z"; - var REACT_DOM_URL = "https://unpkg.com/react-dom@18.3.1/umd/react-dom.production.min.js"; - var REACT_DOM_SRI = "sha384-gTGxhz21lVGYNMcdJOyq01Edg0jhn/c22nsx0kyqP0TxaV5WVdsSH1fSDUf5YJj1"; - var BABEL_URL = "https://unpkg.com/@babel/standalone@7.29.0/babel.min.js"; - var BABEL_SRI = "sha384-m08KidiNqLdpJqLq95G/LEi8Qvjl/xUYll3QILypMoQ65QorJ9Lvtp2RXYGBFj1y"; - function cdnScriptFor(url, sri) { - const res = window.__resources; - const v = res ? res[url] : void 0; - return typeof v === "string" && v ? { src: v } : { src: url, integrity: sri }; - } - - // src/external.ts - var isCustomElementName = (n) => !n.includes(".") && n.includes("-"); - function isRenderableType(g) { - if (typeof g === "function") return !isElementClass(g); - return typeof g === "object" && g !== null && typeof g.$$typeof === "symbol"; - } - function resolveDottedPath(root, name) { - let cur = root; - for (const seg of name.split(".")) { - if (cur == null) return void 0; - cur = cur[seg]; - } - return cur; - } - var GLOBAL_POLL_INTERVAL_MS = 50; - var GLOBAL_POLL_TIMEOUT_MS = 3e4; - function createExternalModules(onResolved) { - const cache = /* @__PURE__ */ new Map(); - let babelLoading = null; - const reportedMissing = /* @__PURE__ */ new Map(); - const polling = /* @__PURE__ */ new Set(); - function ensureBabel() { - if (window.Babel) return Promise.resolve(); - if (babelLoading) return babelLoading; - const babel = cdnScriptFor(BABEL_URL, BABEL_SRI); - babelLoading = new Promise((res, rej) => { - const s = document.createElement("script"); - s.src = babel.src; - if (babel.integrity) { - s.integrity = babel.integrity; - s.crossOrigin = "anonymous"; - } - s.onload = () => res(); - s.onerror = rej; - document.head.appendChild(s); - }); - return babelLoading; - } - const pending = /* @__PURE__ */ new Map(); - function load(kind, url, after) { - const existing = pending.get(url); - if (existing) return existing; - cache.set(url, null); - console.info("[dc-runtime] x-import: loading", url, "(" + kind + ")"); - const ready = Promise.all([ - kind === "jsx" ? ensureBabel() : Promise.resolve(), - after ?? Promise.resolve() - ]); - const p = ready.then(() => { - const pre = bundledBlob(url); - if (pre) return pre.text(); - return fetch(url).then((r) => { - if (!r.ok) throw new Error("HTTP " + r.status); - return r.text(); - }); - }).then((src) => { - const code = kind === "jsx" ? window.Babel.transform(src, { - filename: url, - presets: ["react", "typescript"] - }).code : src; - const module = { exports: {} }; - const before = new Set(Object.keys(window)); - //! nosemgrep: eval-and-function-constructor - new Function("React", "module", "exports", "require", code)( - getReact(), - module, - module.exports, - () => ({}) - ); - const globals = {}; - for (const k of Object.keys(window)) { - if (!before.has(k) && typeof window[k] === "function") { - globals[k] = window[k]; - } - } - cache.set(url, { mod: module.exports, globals }); - console.info( - "[dc-runtime] x-import: loaded", - url, - "\u2014 exports:", - Object.keys(module.exports), - "window globals:", - Object.keys(globals) - ); - onResolved(); - }).catch((e) => { - cache.set(url, { - mod: {}, - globals: {}, - error: "failed to load: " + (e instanceof Error && e.message ? e.message : String(e)) - }); - console.error( - "[dc-runtime] x-import: FAILED to load", - url, - "(" + kind + ")", - e - ); - onResolved(); - }); - pending.set(url, p); - return p; - } - function resolve2(url, name) { - const entry = cache.get(url); - if (!entry) return null; - const { mod, globals } = entry; - const C = mod && mod[name] || globals && globals[name] || typeof window !== "undefined" && window[name] || mod && mod.default; - if (typeof C === "function") return C; - const key = url + "\0" + name; - if (!reportedMissing.has(key)) { - reportedMissing.set( - key, - entry.error || 'no export named "' + name + '" (has: ' + Object.keys(mod).join(", ") + ")" - ); - console.error( - "[dc-runtime] x-import: module", - url, - "loaded but has no component named", - JSON.stringify(name), - "\u2014 available exports:", - Object.keys(mod), - "window globals:", - Object.keys(globals), - ". The module must `module.exports = {" + name + "}` or set `window." + name + "`." - ); - } - return null; - } - function waitForGlobal(name) { - if (polling.has(name)) return; - polling.add(name); - const started = Date.now(); - const isCE = isCustomElementName(name); - const tick = () => { - const found = isCE ? customElements.get(name) : isRenderableType(resolveDottedPath(window, name)); - if (found) { - polling.delete(name); - onResolved(); - return; - } - if (Date.now() - started >= GLOBAL_POLL_TIMEOUT_MS) { - console.warn( - "[dc-runtime] x-import: global", - JSON.stringify(name), - "never appeared on window after " + GLOBAL_POLL_TIMEOUT_MS + "ms" - ); - return; - } - setTimeout(tick, GLOBAL_POLL_INTERVAL_MS); - }; - setTimeout(tick, GLOBAL_POLL_INTERVAL_MS); - } - function resolveGlobal(url, name) { - const isCE = isCustomElementName(name); - if (!url) { - if (isCE) { - if (customElements.get(name)) return name; - waitForGlobal(name); - return null; - } - const g2 = resolveDottedPath(window, name); - if (isRenderableType(g2)) return g2; - waitForGlobal(name); - return null; - } - const entry = cache.get(url); - if (!entry) return null; - if (isCE && customElements.get(name)) return name; - const g = entry.globals[name] ?? resolveDottedPath(window, name); - if (isRenderableType(g)) return g; - if (name.includes(".")) return null; - const key = url + "\0global\0" + name; - if (!reportedMissing.has(key)) { - reportedMissing.set(key, null); - if (isCE && !customElements.get(name)) { - console.warn( - "[dc-runtime] x-import:", - url, - "loaded but no custom element", - JSON.stringify(name), - "is registered and window." + name + " is not a function \u2014 rendering <" + name + "> as an unknown element." - ); - } - } - return name; - } - function getError(url, name) { - const entry = cache.get(url); - if (entry?.error) return entry.error; - return reportedMissing.get(url + "\0" + name) || null; - } - return { load, resolve: resolve2, resolveGlobal, getError }; - } - function isElementClass(g) { - try { - return typeof g === "function" && typeof HTMLElement !== "undefined" && g.prototype instanceof HTMLElement; - } catch { - return false; - } - } - - // src/atomics.ts - var ATOMIC_CSS = ( - // layout - ".fx{display:flex}.col{display:flex;flex-direction:column}.grid{display:grid}.ac{align-items:center}.jc{justify-content:center}.jb{justify-content:space-between}.f1{flex:1}.noshrink{flex-shrink:0}.wrap{flex-wrap:wrap}.fw5{font-weight:500}.fw6{font-weight:600}.fw7{font-weight:700}.fw8{font-weight:800}.fs11{font-size:11px}.fs12{font-size:12px}.fs13{font-size:13px}.fs14{font-size:14px}.fs15{font-size:15px}.fs16{font-size:16px}.fs20{font-size:20px}.fs22{font-size:22px}.upper{text-transform:uppercase}.tc{text-align:center}.nowrap{white-space:nowrap}.gap8{gap:8px}.gap10{gap:10px}.gap12{gap:12px}.gap16{gap:16px}.gap24{gap:24px}.m0{margin:0}.mt8{margin-top:8px}.mt12{margin-top:12px}.mt16{margin-top:16px}.mb8{margin-bottom:8px}.mb12{margin-bottom:12px}.mb16{margin-bottom:16px}.posrel{position:relative}.posabs{position:absolute}.round{border-radius:50%}.ohide{overflow:hidden}.bbox{box-sizing:border-box}.pointer{cursor:pointer}.w100{width:100%}.b0{border:none}" - ); - - // src/helmet.ts - var DESIGN_DOC_MODE_RE = /]*\bname\s*=\s*["']design_doc_mode["'][^>]*\b(?:content|value)\s*=\s*["'](\w+)["']/i; - var CANVAS_BG_LIGHT = "#f0eee6"; - var CANVAS_BG_DARK = "#2e2c26"; - function createHelmetManager(doc, isStreaming) { - const mounted = /* @__PURE__ */ new Set(); - const live = /* @__PURE__ */ new Map(); - let designDocMode = null; - let canvasStyleEl = null; - let appTheme = "light"; - try { - const ds = doc.documentElement.dataset.theme; - appTheme = ds === "dark" || ds === "light" ? ds : new URLSearchParams(doc.defaultView?.location.search ?? "").get( - "theme" - ) === "dark" ? "dark" : "light"; - } catch { - } - function applyCanvasBg() { - if (!canvasStyleEl) return; - const bg = appTheme === "dark" ? CANVAS_BG_DARK : CANVAS_BG_LIGHT; - canvasStyleEl.textContent = `html,body{background:${bg}}#dc-root>.sc-host{position:relative}`; - } - function postDesignMode(mode) { - if (window.parent === window) return; - try { - window.parent.postMessage({ type: "__dc_design_mode", mode }, "*"); - } catch { - } - } - function setDesignDocMode(mode) { - if (mode === designDocMode) return; - designDocMode = mode; - postDesignMode(mode); - if (mode === "canvas") { - doc.documentElement.setAttribute("data-dc-canvas", ""); - canvasStyleEl = doc.createElement("style"); - canvasStyleEl.setAttribute("data-dc-canvas", ""); - applyCanvasBg(); - doc.head.appendChild(canvasStyleEl); - } else { - doc.documentElement.removeAttribute("data-dc-canvas"); - canvasStyleEl?.remove(); - canvasStyleEl = null; - } - } - window.addEventListener("message", (e) => { - const type = e.data && e.data.type; - if (type === "__dc_theme") { - const t = e.data.theme; - if (t === "light" || t === "dark") { - appTheme = t; - applyCanvasBg(); - } - return; - } - if (!designDocMode || type !== "__dc_probe") return; - postDesignMode(designDocMode); - }); - function compile(node) { - const raw = [...node.children]; - const helmetClosed = node.nextSibling != null || node.parentNode?.nextSibling != null; - if (node.hasAttribute("data-dc-atomics") && !mounted.has("__dc-atomics")) { - mounted.add("__dc-atomics"); - const el = doc.createElement("style"); - el.id = "__dc-atomics"; - el.textContent = ATOMIC_CSS; - doc.head.appendChild(el); - } - return (_vals, ctx) => { - const name = ctx && ctx.__name || ""; - const streaming = !!(name && isStreaming(name)); - for (let i = 0; i < raw.length; i++) { - const child = raw[i]; - const tag = child.tagName; - const mayBePartial = streaming && !helmetClosed && i === raw.length - 1; - if (tag === "SCRIPT") { - if (mayBePartial) continue; - const key = "SCRIPT|" + (child.getAttribute("src") || child.textContent || ""); - if (mounted.has(key)) continue; - mounted.add(key); - const el = doc.createElement("script"); - for (const { name: an, value } of [...child.attributes]) - el.setAttribute(an, value); - if (child.textContent) el.textContent = child.textContent; - doc.head.appendChild(el); - } else if (tag === "LINK" || tag === "META") { - if (mayBePartial) continue; - const key = tag + "|" + (child.getAttribute("href") || child.getAttribute("src") || child.outerHTML); - if (mounted.has(key)) continue; - mounted.add(key); - if (tag === "LINK") { - const rel = (child.getAttribute("rel") || "").toLowerCase().split(/\s+/); - const href = (child.getAttribute("href") || "").trim(); - const res = window.__resources; - const pre = res && rel.includes("stylesheet") && !rel.includes("alternate") ? res[href] : void 0; - const blob = typeof pre === "string" && pre ? bundledBlob(pre) : null; - if (blob) { - const el = doc.createElement("style"); - if (child.hasAttribute("disabled")) { - el.setAttribute("media", "not all"); - } else if (child.getAttribute("media")) { - el.setAttribute("media", child.getAttribute("media")); - } - if (child.getAttribute("title")) - el.setAttribute("title", child.getAttribute("title")); - void blob.text().then((css) => { - el.textContent = css; - }); - doc.head.appendChild(el); - continue; - } - } - doc.head.appendChild(child.cloneNode(true)); - } else { - const key = name + "|" + i; - let el = live.get(key); - if (!el || el.tagName !== tag) { - if (el) el.remove(); - el = doc.createElement(tag.toLowerCase()); - live.set(key, el); - doc.head.appendChild(el); - } - for (const { name: an, value } of [...child.attributes]) { - if (el.getAttribute(an) !== value) el.setAttribute(an, value); - } - if (el.textContent !== child.textContent) - el.textContent = child.textContent; - } - } - return null; - }; - } - return { compile, setDesignDocMode }; - } - - // src/pseudo.ts - function createPseudoSheet(doc) { - let el = null; - const cache = /* @__PURE__ */ new Map(); - let n = 0; - return (pseudo, css) => { - const k = pseudo + "|" + css; - const hit = cache.get(k); - if (hit) return hit; - if (!el) { - el = doc.createElement("style"); - doc.head.appendChild(el); - } - const cls = "scp" + (n++).toString(36); - const sel = pseudo === "before" || pseudo === "after" ? "." + cls + "::" + pseudo : "." + cls + ":" + pseudo; - el.sheet.insertRule(sel + "{" + css + "}", el.sheet.cssRules.length); - cache.set(k, cls); - return cls; - }; - } - - // src/registry.ts - function createRegistry() { - const entries = /* @__PURE__ */ Object.create(null); - function get(name) { - return entries[name] || (entries[name] = { - html: "", - tpl: null, - Logic: null, - jsStreaming: false, - htmlStreaming: false, - ver: 0, - subs: /* @__PURE__ */ new Set(), - fetched: false - }); - } - function bump(name) { - const r = get(name); - r.ver++; - for (const fn of r.subs) fn(); - } - return { - entries, - get, - bump, - bumpAll() { - for (const n in entries) bump(n); - } - }; - } - - // src/runtime.ts - var COMPONENT_DIR = "."; - function createRuntime(doc = document) { - const registry = createRegistry(); - const pseudoClass = createPseudoSheet(doc); - const helmet = createHelmetManager( - doc, - (name) => registry.get(name).htmlStreaming - ); - const external = createExternalModules(() => registry.bumpAll()); - const factory = createComponentFactory(registry, ensureFetched); - const host = { - component: (name) => factory.getDC(name), - placeholder: (props) => h(Placeholder, props), - helmet: (node) => helmet.compile(node), - loadExternal: (kind, url, after) => external.load(kind, url, after), - resolveExternal: (url, name) => external.resolve(url, name), - resolveExternalGlobal: (url, name) => external.resolveGlobal(url, name), - resolveExternalError: (url, name) => external.getError(url, name), - pseudoClass - }; - function ensureFetched(name) { - const r = registry.get(name); - if (r.fetched) return; - r.fetched = true; - const url = COMPONENT_DIR + "/" + encodeURIComponent(name) + ".dc.html"; - const res = window.__resources; - const pre = res ? res[url] : void 0; - const target = typeof pre === "string" && pre ? pre : url; - const blob = bundledBlob(target); - (blob ? blob.text() : fetch(target).then((res2) => { - if (!res2.ok) { - console.error( - '[dc-runtime] sibling fetch for "' + name + '" failed:', - url, - "returned", - res2.status, - "\u2014 the reference renders as an empty placeholder." - ); - return ""; - } - return res2.text(); - })).then((t) => { - if (!t) return; - const parsed = parseDcText(t); - if (!parsed) { - console.error( - '[dc-runtime] sibling fetch for "' + name + '":', - url, - "has no block \u2014 not a Design Component." - ); - return; - } - if (parsed.props) r.propsMeta = parsed.props; - if (parsed.preview) r.preview = parsed.preview; - if (parsed.template && !r.html) updateHtml(name, parsed.template); - if (parsed.js && !r.Logic) updateJs(name, parsed.js); - }).catch( - (e) => console.error( - '[dc-runtime] sibling fetch for "' + name + '" threw:', - url, - e - ) - ); - } - let rootName = null; - function updateHtml(name, html) { - const r = registry.get(name); - r.html = html; - if (name === rootName) { - const mode = DESIGN_DOC_MODE_RE.exec(html)?.[1] ?? null; - if (mode || !r.htmlStreaming) helmet.setDesignDocMode(mode); - } - try { - r.tpl = compileTemplate(html, host); - } catch (e) { - console.error("[dc-runtime] template compile FAILED for", name, e); - } - registry.bump(name); - } - function updateJs(name, src) { - const r = registry.get(name); - const seq = r.jsSeq = (r.jsSeq || 0) + 1; - try { - const Cls = evalDcLogic(src); - if (r.jsSeq !== seq) return; - if (typeof Cls !== "function") { - r.logicError = name + ".dc.html: