@@ -32,12 +32,8 @@ import { buildEditorExperienceLayer, summarizeEditorExperienceLayer } from "../s
3232import { buildDebugVisualizationLayer , summarizeDebugVisualizationLayer } from "../shared/debugVisualizationLayer.js" ;
3333import { registerToolBootContract } from "../shared/toolBootContract.js" ;
3434import { createLivePreviewSyncBridge , validateStateBindingPayload } from "../shared/livePreviewSyncChannel.js" ;
35- import { normalizeToolSamplePath , toToolSampleLabel } from "../shared/toolSampleCatalog.js" ;
3635import { addToolModeMetadata , assertStandaloneToolDocument , offerImportMismatchOptions } from "../shared/documentModeGuards.js" ;
3736
38- const SAMPLE_DIRECTORY_PATH = "./samples/" ;
39- const SAMPLE_MANIFEST_PATH = "./samples/sample-manifest.json" ;
40-
4137function normalizeSamplePresetPath ( pathValue ) {
4238 if ( typeof pathValue !== "string" ) {
4339 return "" ;
@@ -384,7 +380,6 @@ class ParallaxEditorApp {
384380 this . refs = { } ;
385381 this . imageCache = new Map ( ) ;
386382 this . imageCacheVersion = 0 ;
387- this . sampleEntries = [ ] ;
388383 this . isSimulationMode = false ;
389384 this . simulation = {
390385 rafId : 0 ,
@@ -460,10 +455,6 @@ class ParallaxEditorApp {
460455 this . renderAll ( ) ;
461456 this . bindRuntimeStateSync ( ) ;
462457 this . queueLivePreviewSync ( "init" ) ;
463- const hasSamplePresetQuery = new URLSearchParams ( window . location . search ) . has ( "samplePresetPath" ) ;
464- if ( this . refs . sampleSelect instanceof HTMLSelectElement && this . refs . loadSampleButton instanceof HTMLButtonElement ) {
465- this . loadSampleManifest ( { quiet : hasSamplePresetQuery } ) ;
466- }
467458 void this . tryLoadPresetFromQuery ( ) ;
468459 }
469460
@@ -498,8 +489,6 @@ class ParallaxEditorApp {
498489 this . refs . mapHeightInput = rootDocument . getElementById ( "mapHeightInput" ) ;
499490 this . refs . tileSizeInput = rootDocument . getElementById ( "tileSizeInput" ) ;
500491 this . refs . applyMapMetaButton = rootDocument . getElementById ( "applyMapMetaButton" ) ;
501- this . refs . sampleSelect = rootDocument . getElementById ( "sampleSelect" ) ;
502- this . refs . loadSampleButton = rootDocument . getElementById ( "loadSampleButton" ) ;
503492
504493 this . refs . layerList = rootDocument . getElementById ( "layerList" ) ;
505494 this . refs . newLayerNameInput = rootDocument . getElementById ( "newLayerNameInput" ) ;
@@ -588,13 +577,6 @@ class ParallaxEditorApp {
588577
589578 this . refs . applyMapMetaButton . addEventListener ( "click" , ( ) => this . applyMapMetaFromInputs ( ) ) ;
590579 this . refs . projectNameInput . addEventListener ( "change" , ( ) => this . applyMapMetaFromInputs ( ) ) ;
591- if ( this . refs . loadSampleButton instanceof HTMLButtonElement && this . refs . sampleSelect instanceof HTMLSelectElement ) {
592- this . refs . loadSampleButton . addEventListener ( "click" , ( ) => this . handleLoadSelectedSample ( ) ) ;
593- this . refs . sampleSelect . addEventListener ( "change" , ( ) => this . handleSampleSelectionChanged ( ) ) ;
594- this . refs . sampleSelect . addEventListener ( "focus" , ( ) => {
595- void this . loadSampleManifest ( { quiet : true } ) ;
596- } ) ;
597- }
598580
599581 this . refs . addLayerButton . addEventListener ( "click" , ( ) => this . addLayer ( ) ) ;
600582 this . refs . removeLayerButton . addEventListener ( "click" , ( ) => this . removeSelectedLayer ( ) ) ;
@@ -989,192 +971,6 @@ class ParallaxEditorApp {
989971 }
990972 }
991973
992- createSampleEntry ( pathValue , labelHint = "" , idHint = "" ) {
993- const path = normalizeToolSamplePath ( pathValue ) ;
994- if ( ! path ) {
995- return null ;
996- }
997- const normalizedLabel = typeof labelHint === "string" ? labelHint . trim ( ) : "" ;
998- const fallbackLabel = toToolSampleLabel ( path ) ;
999- return {
1000- id : typeof idHint === "string" && idHint . trim ( ) ? idHint . trim ( ) : path ,
1001- label : normalizedLabel && ! / [ \\ / ] / . test ( normalizedLabel ) ? normalizedLabel : fallbackLabel ,
1002- path
1003- } ;
1004- }
1005-
1006- async discoverSampleEntriesFromDirectory ( ) {
1007- const directoryUrl = new URL ( SAMPLE_DIRECTORY_PATH , window . location . href ) ;
1008- const response = await fetch ( directoryUrl . toString ( ) , { cache : "no-store" } ) ;
1009- if ( ! response . ok ) {
1010- throw new Error ( `Directory request failed (${ response . status } ).` ) ;
1011- }
1012-
1013- const html = await response . text ( ) ;
1014- const parser = new DOMParser ( ) ;
1015- const documentModel = parser . parseFromString ( html , "text/html" ) ;
1016- const anchors = Array . from ( documentModel . querySelectorAll ( "a[href]" ) ) ;
1017- const discovered = [ ] ;
1018- const seenPaths = new Set ( ) ;
1019-
1020- anchors . forEach ( ( anchor ) => {
1021- const href = anchor . getAttribute ( "href" ) ;
1022- if ( ! href ) {
1023- return ;
1024- }
1025- const resolved = new URL ( href , directoryUrl ) ;
1026- const fileName = decodeURIComponent ( ( resolved . pathname . split ( "/" ) . pop ( ) || "" ) . trim ( ) ) ;
1027- if ( ! fileName || ! fileName . toLowerCase ( ) . endsWith ( ".json" ) ) {
1028- return ;
1029- }
1030- if ( fileName . toLowerCase ( ) === "sample-manifest.json" ) {
1031- return ;
1032- }
1033-
1034- const entry = this . createSampleEntry ( fileName , anchor . textContent || "" , fileName ) ;
1035- if ( ! entry || seenPaths . has ( entry . path ) ) {
1036- return ;
1037- }
1038- seenPaths . add ( entry . path ) ;
1039- discovered . push ( entry ) ;
1040- } ) ;
1041-
1042- discovered . sort ( ( left , right ) => left . label . localeCompare ( right . label ) ) ;
1043- return discovered ;
1044- }
1045-
1046- collectSampleEntriesFromManifest ( manifest ) {
1047- const rawSamples = Array . isArray ( manifest ?. samples ) ? manifest . samples : [ ] ;
1048- return rawSamples
1049- . map ( ( entry ) => this . createSampleEntry ( entry ?. path , entry ?. label , entry ?. id ) )
1050- . filter ( ( entry ) => entry !== null ) ;
1051- }
1052-
1053- async loadSampleManifest ( options = { } ) {
1054- if ( ! ( this . refs . sampleSelect instanceof HTMLSelectElement ) || ! ( this . refs . loadSampleButton instanceof HTMLButtonElement ) ) {
1055- this . sampleEntries = [ ] ;
1056- return ;
1057- }
1058- const quiet = options . quiet === true ;
1059- const previousSelection = normalizeToolSamplePath ( this . refs . sampleSelect . value ) ;
1060- if ( ! quiet ) {
1061- this . refs . sampleSelect . innerHTML = "<option value=\"\">Loading samples...</option>" ;
1062- this . refs . loadSampleButton . disabled = true ;
1063- }
1064-
1065- try {
1066- const sampleEntries = await this . discoverSampleEntriesFromDirectory ( ) ;
1067- if ( sampleEntries . length === 0 ) {
1068- throw new Error ( "No sample JSON files were discovered in ./samples/." ) ;
1069- }
1070- this . sampleEntries = sampleEntries ;
1071- this . renderSampleOptions ( previousSelection ) ;
1072- if ( ! quiet ) {
1073- this . updateStatus ( `Loaded ${ sampleEntries . length } samples from ${ SAMPLE_DIRECTORY_PATH } .` ) ;
1074- }
1075- return ;
1076- } catch ( directoryError ) {
1077- try {
1078- const manifestUrl = new URL ( SAMPLE_MANIFEST_PATH , window . location . href ) ;
1079- const response = await fetch ( manifestUrl . toString ( ) , { cache : "no-store" } ) ;
1080- if ( ! response . ok ) {
1081- throw new Error ( `Manifest request failed (${ response . status } ).` ) ;
1082- }
1083-
1084- const manifest = await response . json ( ) ;
1085- const sampleEntries = this . collectSampleEntriesFromManifest ( manifest ) ;
1086- if ( sampleEntries . length === 0 ) {
1087- throw new Error ( "Sample manifest had no valid entries." ) ;
1088- }
1089-
1090- this . sampleEntries = sampleEntries ;
1091- this . renderSampleOptions ( previousSelection ) ;
1092- if ( ! quiet ) {
1093- this . updateStatus ( `Loaded ${ sampleEntries . length } samples from ${ SAMPLE_MANIFEST_PATH } .` ) ;
1094- }
1095- } catch ( error ) {
1096- this . sampleEntries = [ ] ;
1097- this . renderSampleOptions ( previousSelection ) ;
1098- if ( ! quiet ) {
1099- this . updateStatus ( `Sample discovery unavailable: ${ error instanceof Error ? error . message : "unknown error" } ` ) ;
1100- }
1101- }
1102- }
1103- }
1104-
1105- renderSampleOptions ( preferredPath = "" ) {
1106- if ( ! ( this . refs . sampleSelect instanceof HTMLSelectElement ) || ! ( this . refs . loadSampleButton instanceof HTMLButtonElement ) ) {
1107- return ;
1108- }
1109- const select = this . refs . sampleSelect ;
1110- select . innerHTML = "" ;
1111-
1112- if ( this . sampleEntries . length === 0 ) {
1113- const option = document . createElement ( "option" ) ;
1114- option . value = "" ;
1115- option . textContent = "No samples available" ;
1116- select . appendChild ( option ) ;
1117- this . refs . loadSampleButton . disabled = true ;
1118- return ;
1119- }
1120-
1121- const promptOption = document . createElement ( "option" ) ;
1122- promptOption . value = "" ;
1123- promptOption . textContent = "Select a sample..." ;
1124- select . appendChild ( promptOption ) ;
1125-
1126- this . sampleEntries . forEach ( ( entry ) => {
1127- const option = document . createElement ( "option" ) ;
1128- option . value = entry . path ;
1129- option . textContent = entry . label ;
1130- select . appendChild ( option ) ;
1131- } ) ;
1132-
1133- if ( preferredPath && this . sampleEntries . some ( ( entry ) => entry . path === preferredPath ) ) {
1134- select . value = preferredPath ;
1135- }
1136- this . refs . loadSampleButton . disabled = false ;
1137- }
1138-
1139- handleSampleSelectionChanged ( ) {
1140- if ( ! ( this . refs . sampleSelect instanceof HTMLSelectElement ) ) {
1141- return ;
1142- }
1143- const selectedPath = normalizeToolSamplePath ( this . refs . sampleSelect . value ) ;
1144- if ( ! selectedPath ) {
1145- return ;
1146- }
1147- this . updateStatus ( `Sample selected: ${ selectedPath } ` ) ;
1148- }
1149-
1150- async handleLoadSelectedSample ( ) {
1151- if ( ! ( this . refs . sampleSelect instanceof HTMLSelectElement ) ) {
1152- this . updateStatus ( "Preset loading is available from sample launch context." ) ;
1153- return ;
1154- }
1155- const selectedPath = normalizeToolSamplePath ( this . refs . sampleSelect . value ) ;
1156- if ( ! selectedPath ) {
1157- this . updateStatus ( "Select a sample before loading." ) ;
1158- return ;
1159- }
1160-
1161- this . exitSimulationMode ( ) ;
1162- try {
1163- const sampleUrl = new URL ( selectedPath , window . location . href ) ;
1164- const response = await fetch ( sampleUrl . toString ( ) , { cache : "no-store" } ) ;
1165- if ( ! response . ok ) {
1166- throw new Error ( `Sample request failed (${ response . status } ).` ) ;
1167- }
1168-
1169- const raw = await response . json ( ) ;
1170- this . applyParallaxDocument ( extractParallaxDocument ( raw ) ) ;
1171- this . queueLivePreviewSync ( "load-sample" ) ;
1172- this . updateStatus ( `Loaded sample ${ selectedPath } .` ) ;
1173- } catch ( error ) {
1174- this . updateStatus ( `Sample load failed: ${ error instanceof Error ? error . message : "unknown error" } ` ) ;
1175- }
1176- }
1177-
1178974 async tryLoadPresetFromQuery ( ) {
1179975 const searchParams = new URLSearchParams ( window . location . search ) ;
1180976 const samplePresetPath = normalizeSamplePresetPath ( searchParams . get ( "samplePresetPath" ) || "" ) ;
0 commit comments