@vgai/editor 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/README.md +35 -0
- package/dist/a/b/c/test-nested.json +1 -0
- package/dist/assets/CCDIKSolver-Dz-ysxZF.js +1 -0
- package/dist/assets/SelectionBox-BXsv_6aH.js +1 -0
- package/dist/assets/browser-project-scripts-DOru4L1x.js +2 -0
- package/dist/assets/browserAll-CEkWYlFk.js +1 -0
- package/dist/assets/collision-world-DniMB0qq.glb +0 -0
- package/dist/assets/create-runtime-DYIWr3va.js +1 -0
- package/dist/assets/data-asset-Bb9sIM7i.js +5 -0
- package/dist/assets/esbuild-BHljloGq.wasm +0 -0
- package/dist/assets/fake-three-BMTQ9rl_.js +1 -0
- package/dist/assets/game-8SDZPPgH.js +1 -0
- package/dist/assets/game-BI111o5f.js +10 -0
- package/dist/assets/game-CevorxyV.js +1 -0
- package/dist/assets/game-Di1H0gFj.js +1 -0
- package/dist/assets/game-Di7XlywD.js +1 -0
- package/dist/assets/game-DjnCaw8R.js +1 -0
- package/dist/assets/game-Q9A0aXSV.js +1 -0
- package/dist/assets/game-pt_1lQLv.js +1 -0
- package/dist/assets/game-source-CvidN7AB.js +1 -0
- package/dist/assets/game-xsOho_wg.js +83 -0
- package/dist/assets/index-Bp5cecD6.js +12 -0
- package/dist/assets/index-CPVV6pjw.js +1 -0
- package/dist/assets/index-CpOnYyeD.js +213 -0
- package/dist/assets/index-Cs8xwv3e.js +1 -0
- package/dist/assets/index-DL7RcQ0n.js +27 -0
- package/dist/assets/index-Dr8H_6Rl.js +1 -0
- package/dist/assets/index-_bCaipUk.js +13650 -0
- package/dist/assets/ingest-siblings-Dz8eEqrV.js +1 -0
- package/dist/assets/mount-manifest-Bhk0ohsl.js +1 -0
- package/dist/assets/recast-navigation.wasm-compat-CvP4UGK6.js +1 -0
- package/dist/assets/scene-query-BivAHhJu.js +1 -0
- package/dist/assets/stats.module--VATS4Kh.js +1 -0
- package/dist/assets/webworkerAll-BLrH0F6F.js +1 -0
- package/dist/assets/xstate-animation-binding-1NGLmw6y.js +1 -0
- package/dist/assets/xstate.esm-BgUD33nl.js +3 -0
- package/dist/index.html +37 -0
- package/dist/ingest/racing-game/UPSTREAM.md +68 -0
- package/dist/ingest/racing-game/a/Inter-Black.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-Black.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-BlackItalic.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-BlackItalic.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-Bold.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-Bold.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-BoldItalic.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-BoldItalic.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-ExtraBold.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-ExtraBold.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-ExtraBoldItalic.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-ExtraBoldItalic.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-ExtraLight.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-ExtraLight.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-ExtraLightItalic.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-ExtraLightItalic.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-Italic.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-Italic.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-Light.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-Light.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-LightItalic.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-LightItalic.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-Medium.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-Medium.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-MediumItalic.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-MediumItalic.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-Regular.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-Regular.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-SemiBold.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-SemiBold.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-SemiBoldItalic.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-SemiBoldItalic.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-Thin.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-Thin.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-ThinItalic.woff +0 -0
- package/dist/ingest/racing-game/a/Inter-ThinItalic.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-italic.var.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter-roman.var.woff2 +0 -0
- package/dist/ingest/racing-game/a/Inter.var.woff2 +0 -0
- package/dist/ingest/racing-game/a/index.css +1 -0
- package/dist/ingest/racing-game/images/bronze.png +0 -0
- package/dist/ingest/racing-game/images/gold.png +0 -0
- package/dist/ingest/racing-game/images/silver.png +0 -0
- package/dist/ingest/racing-game/index.html +15 -0
- package/dist/ingest/racing-game/models/chassis-draco.glb +0 -0
- package/dist/ingest/racing-game/models/track-draco.glb +0 -0
- package/dist/ingest/racing-game/models/wheel-draco.glb +0 -0
- package/dist/ingest/racing-game/rg-entry.js +1 -0
- package/dist/ingest/racing-game/sounds/accelerate.mp3 +0 -0
- package/dist/ingest/racing-game/sounds/boost.mp3 +0 -0
- package/dist/ingest/racing-game/sounds/crash.mp3 +0 -0
- package/dist/ingest/racing-game/sounds/engine.mp3 +0 -0
- package/dist/ingest/racing-game/sounds/honk.mp3 +0 -0
- package/dist/ingest/racing-game/sounds/tire-brake.mp3 +0 -0
- package/dist/ingest/racing-game/sounds/train.mp3 +0 -0
- package/dist/ingest/racing-game/sounds/water.mp3 +0 -0
- package/dist/ingest/racing-game/textures/cursor.svg +3 -0
- package/dist/ingest/racing-game/textures/dikhololo_night_1k.hdr +0 -0
- package/dist/ingest/racing-game/textures/heightmap_1024.png +0 -0
- package/dist/ingest/racing-game/textures/mask.svg +11 -0
- package/dist/ingest/racing-game/textures/no_sound.png +0 -0
- package/dist/ingest/racing-game/three-r139.module.js +50617 -0
- package/dist/ingest/racing-game/vendor.js +179 -0
- package/dist/ingest/racing-game/vgai.game.json +20 -0
- package/dist/ingest/simcity/UPSTREAM.md +65 -0
- package/dist/ingest/simcity/favicon.ico +0 -0
- package/dist/ingest/simcity/fonts/Bebas-Regular.otf +0 -0
- package/dist/ingest/simcity/fonts/Digitalt.otf +0 -0
- package/dist/ingest/simcity/fonts/Stanberry.ttf +0 -0
- package/dist/ingest/simcity/icons/bulldozer-color.png +0 -0
- package/dist/ingest/simcity/icons/bulldozer.png +0 -0
- package/dist/ingest/simcity/icons/calendar.png +0 -0
- package/dist/ingest/simcity/icons/factory-color.png +0 -0
- package/dist/ingest/simcity/icons/factory.png +0 -0
- package/dist/ingest/simcity/icons/house-color.png +0 -0
- package/dist/ingest/simcity/icons/house.png +0 -0
- package/dist/ingest/simcity/icons/job.png +0 -0
- package/dist/ingest/simcity/icons/office.png +0 -0
- package/dist/ingest/simcity/icons/pause-color.png +0 -0
- package/dist/ingest/simcity/icons/pause.png +0 -0
- package/dist/ingest/simcity/icons/person.png +0 -0
- package/dist/ingest/simcity/icons/play-color.png +0 -0
- package/dist/ingest/simcity/icons/play.png +0 -0
- package/dist/ingest/simcity/icons/power-color.png +0 -0
- package/dist/ingest/simcity/icons/power-line-color.png +0 -0
- package/dist/ingest/simcity/icons/power.png +0 -0
- package/dist/ingest/simcity/icons/road-color.png +0 -0
- package/dist/ingest/simcity/icons/road.png +0 -0
- package/dist/ingest/simcity/icons/select-color.png +0 -0
- package/dist/ingest/simcity/icons/select.png +0 -0
- package/dist/ingest/simcity/icons/store-color.png +0 -0
- package/dist/ingest/simcity/index.html +94 -0
- package/dist/ingest/simcity/index.js +58 -0
- package/dist/ingest/simcity/main.css +233 -0
- package/dist/ingest/simcity/models/armored-truck.glb +0 -0
- package/dist/ingest/simcity/models/building-block-4floor-corner.glb +0 -0
- package/dist/ingest/simcity/models/building-block-4floor-short.glb +0 -0
- package/dist/ingest/simcity/models/building-block-5floor.glb +0 -0
- package/dist/ingest/simcity/models/building-burger-joint.glb +0 -0
- package/dist/ingest/simcity/models/building-cafe.glb +0 -0
- package/dist/ingest/simcity/models/building-casino.glb +0 -0
- package/dist/ingest/simcity/models/building-cinema.glb +0 -0
- package/dist/ingest/simcity/models/building-house-block-big.glb +0 -0
- package/dist/ingest/simcity/models/building-house-family-large.glb +0 -0
- package/dist/ingest/simcity/models/building-house-family-small.glb +0 -0
- package/dist/ingest/simcity/models/building-office-balcony.glb +0 -0
- package/dist/ingest/simcity/models/building-office-big.glb +0 -0
- package/dist/ingest/simcity/models/building-office-pyramid.glb +0 -0
- package/dist/ingest/simcity/models/building-office-tall.glb +0 -0
- package/dist/ingest/simcity/models/building-office.glb +0 -0
- package/dist/ingest/simcity/models/building-restaurant.glb +0 -0
- package/dist/ingest/simcity/models/building-skyscraper.glb +0 -0
- package/dist/ingest/simcity/models/car-ambulance-pickup.glb +0 -0
- package/dist/ingest/simcity/models/car-baywatch.glb +0 -0
- package/dist/ingest/simcity/models/car-hippie-van.glb +0 -0
- package/dist/ingest/simcity/models/car-passenger-race.glb +0 -0
- package/dist/ingest/simcity/models/car-passenger.glb +0 -0
- package/dist/ingest/simcity/models/car-police.glb +0 -0
- package/dist/ingest/simcity/models/car-taxi.glb +0 -0
- package/dist/ingest/simcity/models/car-tow-truck.glb +0 -0
- package/dist/ingest/simcity/models/car-truck-dump.glb +0 -0
- package/dist/ingest/simcity/models/car-veteran.glb +0 -0
- package/dist/ingest/simcity/models/construction-small.glb +0 -0
- package/dist/ingest/simcity/models/data-center.glb +0 -0
- package/dist/ingest/simcity/models/industry-factory-old.glb +0 -0
- package/dist/ingest/simcity/models/industry-factory.glb +0 -0
- package/dist/ingest/simcity/models/industry-refinery.glb +0 -0
- package/dist/ingest/simcity/models/industry-warehouse.glb +0 -0
- package/dist/ingest/simcity/models/power_line_pole_modified.glb +0 -0
- package/dist/ingest/simcity/models/tile-plain_grass.glb +0 -0
- package/dist/ingest/simcity/models/tile-road-curve.glb +0 -0
- package/dist/ingest/simcity/models/tile-road-end.glb +0 -0
- package/dist/ingest/simcity/models/tile-road-intersection-t.glb +0 -0
- package/dist/ingest/simcity/models/tile-road-intersection.glb +0 -0
- package/dist/ingest/simcity/models/tile-road-straight.glb +0 -0
- package/dist/ingest/simcity/models/truck.glb +0 -0
- package/dist/ingest/simcity/statusIcons/no-power.png +0 -0
- package/dist/ingest/simcity/statusIcons/no-road-access.png +0 -0
- package/dist/ingest/simcity/textures/base.png +0 -0
- package/dist/ingest/simcity/textures/grid.png +0 -0
- package/dist/ingest/simcity/textures/specular.png +0 -0
- package/dist/ingest/simcity/three-r155.module.js +51466 -0
- package/dist/ingest/simcity/vgai.game.json +20 -0
- package/dist/ingest/tanks/UPSTREAM.md +69 -0
- package/dist/ingest/tanks/index.html +214 -0
- package/dist/ingest/tanks/models/pixelTank.fbx +0 -0
- package/dist/ingest/tanks/tanks-entry.js +92 -0
- package/dist/ingest/tanks/three-r170.module.js +54571 -0
- package/dist/ingest/tanks/vgai.game.json +20 -0
- package/dist/inputmaps/default.inputmap.json +41 -0
- package/dist/jsm/libs/draco/gltf/draco_decoder.js +33 -0
- package/dist/jsm/libs/draco/gltf/draco_decoder.wasm +0 -0
- package/dist/jsm/libs/draco/gltf/draco_wasm_wrapper.js +116 -0
- package/dist/scenes/untitled.vscn.json +29 -0
- package/dist/textures/waternormals.jpg +0 -0
- package/dist-server/packaged.mjs +18155 -0
- package/package.json +36 -0
- package/server/asset-library-routes.ts +833 -0
- package/server/canonical-path.ts +50 -0
- package/server/cloud-asset-catalog.ts +101 -0
- package/server/dev.ts +350 -0
- package/server/editor-server.ts +1537 -0
- package/server/editor-sse.ts +73 -0
- package/server/game-globals-shadow.ts +58 -0
- package/server/local-asset-catalog.ts +163 -0
- package/server/packaged.ts +571 -0
- package/server/prod.ts +75 -0
- package/server/project-optimize-deps-entries.ts +149 -0
- package/server/project-view.ts +65 -0
- package/server/server-utils.ts +430 -0
- package/server/session-registry.ts +93 -0
- package/src/EditorContext.tsx +87 -0
- package/src/achieved-tier.ts +126 -0
- package/src/action-registry.ts +268 -0
- package/src/adapter-resolver.ts +1858 -0
- package/src/asset-events.ts +100 -0
- package/src/authoring/active-adapter.ts +98 -0
- package/src/authoring/active-systems.ts +50 -0
- package/src/authoring/boundary-authoring-adapter.ts +178 -0
- package/src/authoring/composite-authoring-adapter.ts +891 -0
- package/src/authoring/design-time-layers.ts +776 -0
- package/src/authoring/edit-mode-authoring.ts +643 -0
- package/src/authoring/embed-only-adapter.ts +57 -0
- package/src/authoring/ephemeral-persistence.ts +26 -0
- package/src/authoring/eyedropper-session.ts +69 -0
- package/src/authoring/first-party-hierarchy-menu.ts +74 -0
- package/src/authoring/first-party-inspector/AddSectionMenu.tsx +118 -0
- package/src/authoring/first-party-inspector/EnvironmentSection.tsx +550 -0
- package/src/authoring/first-party-inspector/HeaderSection.tsx +329 -0
- package/src/authoring/first-party-inspector/is-first-party-selection.ts +44 -0
- package/src/authoring/first-party-inspector/register.tsx +108 -0
- package/src/authoring/ingest-authoring-adapter.ts +475 -0
- package/src/authoring/ingest-capture.ts +94 -0
- package/src/authoring/ingest-game-adapter.ts +291 -0
- package/src/authoring/ingest-iframe-adapter.ts +38 -0
- package/src/authoring/ingest-iframe-reachable-adapter.ts +401 -0
- package/src/authoring/ingest-overlay.ts +193 -0
- package/src/authoring/layered-pick.ts +87 -0
- package/src/authoring/mount-failure-report.ts +112 -0
- package/src/authoring/overlay-report.ts +52 -0
- package/src/authoring/project-scenes.ts +111 -0
- package/src/authoring/react-dom-authoring-adapter.ts +795 -0
- package/src/authoring/react-inspector-section.tsx +1041 -0
- package/src/authoring/react-world-authoring-adapter.ts +2400 -0
- package/src/authoring/root-activation.ts +61 -0
- package/src/authoring/scene-ui-layer.ts +485 -0
- package/src/authoring/story-overlay.ts +48 -0
- package/src/authoring/ui-authoring-adapter.ts +325 -0
- package/src/authoring/ui-hierarchy-menu.ts +40 -0
- package/src/authoring/ui-inspector-sections.tsx +156 -0
- package/src/authoring/undo-timeline.ts +145 -0
- package/src/authoring/vgai-scene-authoring-adapter.ts +746 -0
- package/src/authoring/viewport-pick-context.ts +31 -0
- package/src/authoring/viewport-raycast.ts +80 -0
- package/src/authoring/world-overlay.ts +76 -0
- package/src/authoring/world-pan-state.ts +115 -0
- package/src/authoring/world-session-state.ts +102 -0
- package/src/authoring/world2d-authoring-adapter.ts +313 -0
- package/src/browser-external-watch.ts +98 -0
- package/src/browser-play-entry.ts +112 -0
- package/src/browser-project-scripts.ts +112 -0
- package/src/browser-transpile.ts +246 -0
- package/src/browser-watch-reload.ts +100 -0
- package/src/command-listener.ts +326 -0
- package/src/components/AlignToolbar.tsx +189 -0
- package/src/components/AppRoot.tsx +73 -0
- package/src/components/AssetBrowser.tsx +502 -0
- package/src/components/BottomPanel.tsx +326 -0
- package/src/components/BuildPanel.tsx +455 -0
- package/src/components/CameraInfo.tsx +56 -0
- package/src/components/CommandPalette.tsx +265 -0
- package/src/components/ConsolePanel.tsx +272 -0
- package/src/components/DataPanel.tsx +1268 -0
- package/src/components/DefaultEditorLayout.tsx +509 -0
- package/src/components/FolderTree.tsx +179 -0
- package/src/components/GameHierarchy.tsx +1349 -0
- package/src/components/Inspector.tsx +671 -0
- package/src/components/InspectorToolSection.tsx +74 -0
- package/src/components/MountFailureBanner.tsx +110 -0
- package/src/components/NetworkSection.tsx +109 -0
- package/src/components/OnlineAssetBrowser.tsx +448 -0
- package/src/components/OverlayReportBanner.tsx +122 -0
- package/src/components/PlayBar.tsx +356 -0
- package/src/components/PrefabSaveDialog.tsx +201 -0
- package/src/components/ProjectHeader.tsx +174 -0
- package/src/components/ProjectScreen.tsx +1004 -0
- package/src/components/RightPanel.tsx +166 -0
- package/src/components/RootActivateDialog.tsx +105 -0
- package/src/components/SaveDialog.tsx +197 -0
- package/src/components/SaveStatus.tsx +69 -0
- package/src/components/StatsOverlay.tsx +35 -0
- package/src/components/ToolHost.tsx +80 -0
- package/src/components/Toolbar.tsx +307 -0
- package/src/components/ViewportOverlay.tsx +234 -0
- package/src/components/ViewportPanel.tsx +369 -0
- package/src/components/WorldContextMenu.tsx +257 -0
- package/src/components/WorldSelectionOverlay.tsx +2003 -0
- package/src/components/WorldTextEditor.tsx +86 -0
- package/src/components/asset-viewers/AssetViewer.tsx +38 -0
- package/src/components/asset-viewers/AudioViewer.tsx +149 -0
- package/src/components/asset-viewers/GenericJsonViewer.tsx +77 -0
- package/src/components/asset-viewers/ImageViewer.tsx +65 -0
- package/src/components/asset-viewers/InputMapViewer.tsx +206 -0
- package/src/components/asset-viewers/ModelViewer.tsx +180 -0
- package/src/components/asset-viewers/OnlineAssetDetail.tsx +236 -0
- package/src/components/data-csv.ts +301 -0
- package/src/components/entity-name-commit.ts +18 -0
- package/src/components/inspector-property-grouping.ts +65 -0
- package/src/components/inspector-widgets/AlignmentGrid.tsx +188 -0
- package/src/components/inspector-widgets/BorderEditor.tsx +305 -0
- package/src/components/inspector-widgets/ColorPicker.tsx +548 -0
- package/src/components/inspector-widgets/FilterEditor.tsx +108 -0
- package/src/components/inspector-widgets/FontPicker.tsx +196 -0
- package/src/components/inspector-widgets/GradientEditor.tsx +277 -0
- package/src/components/inspector-widgets/ScrubbableInput.tsx +152 -0
- package/src/components/inspector-widgets/ShadowEditor.tsx +332 -0
- package/src/components/inspector-widgets/color-utils.ts +202 -0
- package/src/components/inspector-widgets/gallery-main.tsx +167 -0
- package/src/components/inspector-widgets/index.ts +22 -0
- package/src/components/inspector-widgets/shared.tsx +135 -0
- package/src/components/inspectors/AnimationSection.tsx +143 -0
- package/src/components/inspectors/AudioSection.tsx +215 -0
- package/src/components/inspectors/BoneAttachmentSection.tsx +82 -0
- package/src/components/inspectors/CameraSection.tsx +105 -0
- package/src/components/inspectors/ComponentsSection.tsx +358 -0
- package/src/components/inspectors/JointsSection.tsx +255 -0
- package/src/components/inspectors/LightSection.tsx +116 -0
- package/src/components/inspectors/MaterialSection.tsx +1189 -0
- package/src/components/inspectors/MeshSection.tsx +99 -0
- package/src/components/inspectors/NavigationSection.tsx +58 -0
- package/src/components/inspectors/ParticleSection.tsx +681 -0
- package/src/components/inspectors/PhysicsSection.tsx +326 -0
- package/src/components/inspectors/PostProcessingSection.tsx +1290 -0
- package/src/components/inspectors/RenderingSection.tsx +109 -0
- package/src/components/inspectors/ShadowSection.tsx +84 -0
- package/src/components/inspectors/SplineSection.tsx +191 -0
- package/src/components/inspectors/TransformSection.tsx +191 -0
- package/src/components/inspectors/json-schema-fields.ts +281 -0
- package/src/components/inspectors/multi-edit-utils.ts +49 -0
- package/src/components/inspectors/zod-fields.ts +184 -0
- package/src/components/primitives/ColorInput.tsx +109 -0
- package/src/components/primitives/JsonInput.tsx +98 -0
- package/src/components/primitives/NumberInput.tsx +164 -0
- package/src/components/primitives/Panel.tsx +68 -0
- package/src/components/primitives/SectionHeader.tsx +45 -0
- package/src/components/primitives/Tooltip.tsx +82 -0
- package/src/components/primitives/Vec3Input.tsx +62 -0
- package/src/components/world-overlay-gestures.ts +1438 -0
- package/src/doctor/data-checks.ts +285 -0
- package/src/doctor/report.ts +386 -0
- package/src/editor-api.ts +700 -0
- package/src/editor-console.ts +194 -0
- package/src/editor-hotkeys.ts +441 -0
- package/src/editor-layers.ts +2 -0
- package/src/editor-mode.ts +28 -0
- package/src/editor-store.ts +2225 -0
- package/src/editor-viewport.ts +1924 -0
- package/src/entity-factory.ts +221 -0
- package/src/game-globals-prelude.ts +27 -0
- package/src/gated-globals.ts +131 -0
- package/src/generated/setup-by-example.generated.ts +53 -0
- package/src/gizmo-registry.ts +608 -0
- package/src/handle-system.ts +221 -0
- package/src/hierarchy-menu-registry.ts +70 -0
- package/src/hierarchy-rows.ts +73 -0
- package/src/hosted-example.ts +160 -0
- package/src/hotkeys.ts +142 -0
- package/src/ingest/discovery-react.ts +132 -0
- package/src/ingest/discovery.ts +205 -0
- package/src/ingest/discovery2d.ts +204 -0
- package/src/ingest/esm-entry-resolution.ts +102 -0
- package/src/ingest/games/bloom-composer/game.js +99 -0
- package/src/ingest/games/bloom-composer/vgai.game.json +21 -0
- package/src/ingest/games/embed-bundle/embed.html +10 -0
- package/src/ingest/games/embed-bundle/vgai.game.json +21 -0
- package/src/ingest/games/games-fps/assets/collision-world.glb +0 -0
- package/src/ingest/games/games-fps/game.js +479 -0
- package/src/ingest/games/games-fps/vgai.game.json +24 -0
- package/src/ingest/games/iframe-reachable/game-source.js +58 -0
- package/src/ingest/games/iframe-reachable/vgai.game.json +21 -0
- package/src/ingest/games/interactive-cubes/game.js +139 -0
- package/src/ingest/games/interactive-cubes/vgai.game.json +21 -0
- package/src/ingest/games/mismatched-three/fake-three.js +38 -0
- package/src/ingest/games/mismatched-three/game.js +10 -0
- package/src/ingest/games/mismatched-three/vgai.game.json +22 -0
- package/src/ingest/games/own-three-bundled/game.js +43 -0
- package/src/ingest/games/own-three-bundled/vgai.game.json +21 -0
- package/src/ingest/games/pointerlock-maze/game.js +288 -0
- package/src/ingest/games/pointerlock-maze/vgai.game.json +22 -0
- package/src/ingest/games-2d/_fixtures/first-party-scene.scn2d.json +124 -0
- package/src/ingest/games-2d/bubbo-bubbo/vgai.game.json +25 -0
- package/src/ingest/games-2d/bunnymark/game.ts +88 -0
- package/src/ingest/games-2d/bunnymark/vgai.game.json +21 -0
- package/src/ingest/games-2d/flappy/game.ts +148 -0
- package/src/ingest/games-2d/flappy/vgai.game.json +21 -0
- package/src/ingest/games-2d/flappy-pixi/vgai.game.json +25 -0
- package/src/ingest/games-2d/puzzling-potions/vgai.game.json +25 -0
- package/src/ingest/games-2d/tilemap-camera/game.ts +115 -0
- package/src/ingest/games-2d/tilemap-camera/vgai.game.json +21 -0
- package/src/ingest/games-react/react-rpg/entry.tsx +185 -0
- package/src/ingest/games-react/react-rpg/shims.d.ts +26 -0
- package/src/ingest/games-react/react-rpg/src/ui/game-state.tsx +129 -0
- package/src/ingest/games-react/react-rpg/vgai.game.json +21 -0
- package/src/ingest/host-namespace-registry.ts +196 -0
- package/src/ingest/types.ts +127 -0
- package/src/ingest-hierarchy-rows.ts +207 -0
- package/src/ingest-mode.ts +2092 -0
- package/src/ingest-siblings.ts +466 -0
- package/src/initial-scene.ts +194 -0
- package/src/inspector-section-registry.ts +117 -0
- package/src/interactive-edit-scope.ts +34 -0
- package/src/main.tsx +23 -0
- package/src/manifest-project.ts +43 -0
- package/src/model-thumbnail.ts +156 -0
- package/src/module-mode.ts +513 -0
- package/src/navmesh-handler.ts +94 -0
- package/src/packaged-runtime.ts +49 -0
- package/src/play-mode.ts +1148 -0
- package/src/playground/main.ts +206 -0
- package/src/project-manager.ts +173 -0
- package/src/scene-diff.ts +112 -0
- package/src/scene-serializer.ts +144 -0
- package/src/scene-sync.ts +587 -0
- package/src/scene-ui-mode/active-scene-ui.ts +58 -0
- package/src/scene-ui-mode/scene-ui-palette-panel.tsx +152 -0
- package/src/scene-ui-mode/scene-ui-timeline-tab.tsx +29 -0
- package/src/scene-ui-mode/ui-prefab-dialog-host.tsx +74 -0
- package/src/scene-ui-mode/ui-prefab-hierarchy-menu.ts +49 -0
- package/src/scene-ui-mode/ui-prefab-io.ts +76 -0
- package/src/script-loader.ts +143 -0
- package/src/storage/fsa-storage.ts +55 -0
- package/src/storage/handle-storage.ts +150 -0
- package/src/storage/handle-store.ts +116 -0
- package/src/storage/http-storage.ts +137 -0
- package/src/storage/index.ts +147 -0
- package/src/storage/mem-storage.ts +135 -0
- package/src/storage/opfs-storage.ts +25 -0
- package/src/storage/paths.ts +26 -0
- package/src/storage/seed.ts +106 -0
- package/src/storage/types.ts +110 -0
- package/src/tool-loader.ts +291 -0
- package/src/ui-editor/inspector.tsx +563 -0
- package/src/ui-editor/node-ops.ts +266 -0
- package/src/ui-editor/overlay.tsx +380 -0
- package/src/ui-editor/palette.tsx +114 -0
- package/src/ui-editor/react-store.ts +78 -0
- package/src/ui-editor/timeline-panel.tsx +443 -0
- package/src/ui-editor/ui-edit-store.ts +552 -0
- package/src/ui-editor/ui-prefab.ts +95 -0
- package/src/ui-source/inspect.ts +544 -0
- package/src/ui-source/oid-transform.ts +133 -0
- package/src/ui-source/source-write-backend.ts +203 -0
- package/src/ui-source/tailwind-map.ts +174 -0
- package/src/ui-source/writer.ts +1175 -0
- package/src/widgets/index.ts +73 -0
- package/template/.claude/skills/editor/SKILL.md +252 -0
- package/template/CLAUDE.md +512 -0
- package/template/LICENSE +30 -0
- package/template/emit-schemas.ts +42 -0
- package/template/index.html +17 -0
- package/template/package.json +53 -0
- package/template/project.json +9 -0
- package/template/public/audio/ambient-arena.wav +0 -0
- package/template/public/audio/ambient-music.wav +0 -0
- package/template/public/audio/ambient-nature.wav +0 -0
- package/template/public/audio/ambient-wind.wav +0 -0
- package/template/public/inputmaps/default.inputmap.json +41 -0
- package/template/public/jsm/libs/draco/gltf/draco_decoder.js +33 -0
- package/template/public/jsm/libs/draco/gltf/draco_decoder.wasm +0 -0
- package/template/public/jsm/libs/draco/gltf/draco_encoder.js +33 -0
- package/template/public/jsm/libs/draco/gltf/draco_wasm_wrapper.js +116 -0
- package/template/public/scenes/default.vscn.json +43 -0
- package/template/public/scenes/untitled.vscn.json +29 -0
- package/template/public/textures/waternormals.jpg +0 -0
- package/template/server/colyseus-setup.ts +85 -0
- package/template/server/main.ts +34 -0
- package/template/server/rooms/arena-room.ts +420 -0
- package/template/server/rooms/game-room.ts +162 -0
- package/template/server/rooms.ts +15 -0
- package/template/server/tsconfig.json +19 -0
- package/template/src/data/README.md +40 -0
- package/template/src/data/assets.ts +31 -0
- package/template/src/data/tuning.data.json +5 -0
- package/template/src/data/tuning.schema.json +21 -0
- package/template/src/data/tuning.schema.ts +34 -0
- package/template/src/data/tuning.ts +24 -0
- package/template/src/main.ts +157 -0
- package/template/src/scripts/components/data-spinner.ts +45 -0
- package/template/src/scripts/components/scene-camera.ts +40 -0
- package/template/src/scripts/main.ts +94 -0
- package/template/src/scripts/registry.ts +46 -0
- package/template/src/tools/README.md +14 -0
- package/template/src/tools/example.tool.tsx +91 -0
- package/template/src/tools/spin.tool.tsx +101 -0
- package/template/src/ui/Button.tsx +27 -0
- package/template/src/ui/DefaultHud.tsx +40 -0
- package/template/src/ui/KeyHint.tsx +25 -0
- package/template/src/ui/Panel.tsx +52 -0
- package/template/src/ui/RebindPanel.tsx +129 -0
- package/template/src/ui/Slider.tsx +28 -0
- package/template/src/ui/StatusDot.tsx +22 -0
- package/template/src/ui/Toggle.tsx +19 -0
- package/template/src/ui/game-state.tsx +37 -0
- package/template/src/ui/index.ts +7 -0
- package/template/src/ui/mount-default-hud.tsx +19 -0
- package/template/src/ui/mount-ui.ts +15 -0
- package/template/tsconfig.json +36 -0
- package/template/validate-asset-content.ts +78 -0
- package/template/validate-manifest.ts +55 -0
- package/template/validate-scenes.ts +211 -0
- package/template/vgai.game.json +21 -0
- package/template/vite.config.ts +128 -0
- package/vite-plugin-example-assets.ts +60 -0
- package/vite-plugin-game-globals.ts +46 -0
- package/vite-plugin-game-static.ts +71 -0
- package/vite-plugin-project-game-static.ts +84 -0
- package/vite-plugin-react-game-static.ts +98 -0
- package/vite-plugin-react-world-provider.ts +81 -0
- package/vite-plugin-react-world-runtime.ts +76 -0
- package/vite-plugin-ui-oid.ts +561 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SourceWriteBackend — the pending-write flush contract for JSX source edits (T3.2
|
|
3
|
+
* slice 3, design `docs/PERSISTENCE-PROVIDER-DESIGN.md` §4).
|
|
4
|
+
*
|
|
5
|
+
* `UIAuthoringAdapter.persistence.save()` is the de-stub target for this seam. What
|
|
6
|
+
* we found investigating the CURRENT write lifecycle (see `source-edit-panel.tsx`):
|
|
7
|
+
* there is NO pending-write queue — every source edit (a style tweak, a struct op)
|
|
8
|
+
* writes to disk IMMEDIATELY via a raw `fetch` call the instant the user commits it
|
|
9
|
+
* (Enter / blur), server-side through the SAME surgical writer used in unit tests
|
|
10
|
+
* (`ui-source/writer.ts`, invoked by `vite-plugin-ui-oid.ts`'s dev-server
|
|
11
|
+
* middleware). So `save()` has nothing to flush; it is an honest no-op REGARDLESS of
|
|
12
|
+
* whether a backend is wired (see `ui-authoring-adapter.ts`). This seam exists so:
|
|
13
|
+
* - the HTTP wire shape is reachable/testable through an injectable interface
|
|
14
|
+
* instead of a bare `fetch` scattered in the adapter, and
|
|
15
|
+
* - a future batching/offline queue (if one is ever built) has somewhere honest
|
|
16
|
+
* to route writes — this file does NOT invent that queue.
|
|
17
|
+
*
|
|
18
|
+
* The browser/hosted tier (no dev server, e.g. a `--mode web` hosted build) has NO
|
|
19
|
+
* implementation here. Backend absence is surfaced through
|
|
20
|
+
* `persistence.destination`, NOT by flipping `capabilities.persist` to false —
|
|
21
|
+
* see `ui-authoring-adapter.ts`'s doc comment for why that flag deliberately
|
|
22
|
+
* stays `true` (it also gates the separate ui-tree→`.vscn` path). We do NOT
|
|
23
|
+
* fake a save.
|
|
24
|
+
*
|
|
25
|
+
* Explicit non-goal (design §6): the vite plugin's raw `node:fs` writes are
|
|
26
|
+
* server-side and stay exactly as they are — this seam is the CLIENT-facing
|
|
27
|
+
* contract in front of them, not a reroute of their internals through
|
|
28
|
+
* `StorageBackend`.
|
|
29
|
+
*
|
|
30
|
+
* `index()` (T6.2 slice 2, `docs/REACT-WORLD-DESIGN.md` §1.D) is the read-side
|
|
31
|
+
* sibling added for `ReactWorldAuthoringAdapter`'s node labeling
|
|
32
|
+
* (`component:tag`): it exposes the SAME `/__ui-source/index` GET endpoint
|
|
33
|
+
* `vite-plugin-ui-oid.ts` already serves (previously only fetched ad hoc by
|
|
34
|
+
* `source-edit-panel.tsx`) through this one backend seam, rather than a second
|
|
35
|
+
* bespoke fetch call.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
import type { OidEntry } from './oid-transform';
|
|
39
|
+
|
|
40
|
+
/** The source-write operations (+ the OID index read) the dev-server middleware
|
|
41
|
+
* already exposes. */
|
|
42
|
+
export interface SourceWriteBackend {
|
|
43
|
+
/** Surgical inline-style/className edit — the `/__ui-source/write` shape.
|
|
44
|
+
* `appended` (D-A1, wave 13) is true only when the write took the writer's
|
|
45
|
+
* APPEND branch (no prior literal for this prop) — see
|
|
46
|
+
* `ReactWorldAuthoringAdapter.writeStyle`'s append-aware undo (D-A4). */
|
|
47
|
+
writeStyle(
|
|
48
|
+
oid: string,
|
|
49
|
+
prop: string,
|
|
50
|
+
value: string,
|
|
51
|
+
): Promise<{
|
|
52
|
+
changed: boolean;
|
|
53
|
+
dynamic?: boolean;
|
|
54
|
+
route?: string;
|
|
55
|
+
error?: string;
|
|
56
|
+
appended?: boolean;
|
|
57
|
+
}>;
|
|
58
|
+
/**
|
|
59
|
+
* D-A3 (wave 13): surgically REMOVE an appended inline-style property — the
|
|
60
|
+
* correct undo for a write that took the append branch (`appended: true`).
|
|
61
|
+
* Posts the SAME `/__ui-source/write` endpoint `writeStyle` uses, with the
|
|
62
|
+
* `value: null` removal sentinel the middleware routes to `removeInlineStyle`.
|
|
63
|
+
*/
|
|
64
|
+
removeStyle(
|
|
65
|
+
oid: string,
|
|
66
|
+
prop: string,
|
|
67
|
+
): Promise<{ changed: boolean; route?: string; error?: string }>;
|
|
68
|
+
/** Surgical CSS-FILE edit (Cap 2) — the `/__ui-source/css` shape. The client resolves
|
|
69
|
+
* the target rule (source file + selector) from live matched-rule data and sends it;
|
|
70
|
+
* the server edits that file in place. `generated: true` means the selector was not
|
|
71
|
+
* found in source (generated CSS) — the caller re-routes to class/inline.
|
|
72
|
+
* Optional: only a dev-server-backed implementation serves it. */
|
|
73
|
+
writeCss?(
|
|
74
|
+
file: string,
|
|
75
|
+
selector: string,
|
|
76
|
+
prop: string,
|
|
77
|
+
value: string,
|
|
78
|
+
): Promise<{ changed: boolean; generated?: boolean; error?: string }>;
|
|
79
|
+
/** Text-content edit (Cap 3) — the `/__ui-source/text` shape. Replaces a leaf element's
|
|
80
|
+
* pure-text body; `dynamic: true` means the body has an expression/children (refused).
|
|
81
|
+
* `prevText` is the editable text before the edit (for the undo inverse). Optional:
|
|
82
|
+
* only a dev-server-backed implementation serves it. */
|
|
83
|
+
writeText?(
|
|
84
|
+
oid: string,
|
|
85
|
+
text: string,
|
|
86
|
+
): Promise<{ changed: boolean; dynamic?: boolean; prevText?: string | null; error?: string }>;
|
|
87
|
+
/** Component prop / attribute edit (Cap 4) — the `/__ui-source/prop` shape. `oid` is the
|
|
88
|
+
* CALL-SITE oid (the `<Component …>` tag). `dynamic: true` ⇒ the prop is a non-literal
|
|
89
|
+
* expression (refused). Optional: only a dev-server-backed implementation serves it. */
|
|
90
|
+
writeProp?(
|
|
91
|
+
oid: string,
|
|
92
|
+
prop: string,
|
|
93
|
+
value: string,
|
|
94
|
+
): Promise<{ changed: boolean; dynamic?: boolean; error?: string }>;
|
|
95
|
+
/**
|
|
96
|
+
* Structural source edit — the `/__ui-source/struct` shape. Ops: `delete`, `duplicate`,
|
|
97
|
+
* `wrap`/`unwrap`, `create`, `reorder`, `reparent` (Cap 5). Multi-oid ops pass the
|
|
98
|
+
* companion oid(s) + optional `wrapperTag` via `opts`.
|
|
99
|
+
*
|
|
100
|
+
* D-1 (Phase D, spec27 §2): when `changed`, the server ALSO returns the whole
|
|
101
|
+
* touched file's `prevSource`/`newSource` (before/after this op) plus their
|
|
102
|
+
* `prevSha`/`newSha` (sha256, server-computed) — the checksum-guarded
|
|
103
|
+
* whole-file snapshot inverse `ReactWorldAuthoringAdapter.structOp` needs to
|
|
104
|
+
* push ONE undo/redo entry per structural op (a per-OID inverse is unsound
|
|
105
|
+
* here: OIDs are `file:component:tag:nthOccurrence` content signatures,
|
|
106
|
+
* reorder/delete reassign occurrence indices, and delete has no inverse
|
|
107
|
+
* payload of its own). These fields are absent when `changed` is false, and
|
|
108
|
+
* on an implementation that predates D-1 (a bare `{changed}` mock) — either
|
|
109
|
+
* way the caller degrades to "not undoable" rather than crashing.
|
|
110
|
+
*/
|
|
111
|
+
writeStruct(
|
|
112
|
+
oid: string,
|
|
113
|
+
op: string,
|
|
114
|
+
opts?: { targetOid?: string; parentOid?: string; wrapperTag?: string },
|
|
115
|
+
): Promise<{
|
|
116
|
+
changed: boolean;
|
|
117
|
+
error?: string;
|
|
118
|
+
file?: string;
|
|
119
|
+
prevSource?: string;
|
|
120
|
+
newSource?: string;
|
|
121
|
+
prevSha?: string;
|
|
122
|
+
newSha?: string;
|
|
123
|
+
}>;
|
|
124
|
+
/**
|
|
125
|
+
* Batched structural delete — delete-order-residual fix (bug-panel follow-up to
|
|
126
|
+
* the multi-delete corruption fix, 50f90a6d), the `/__ui-source/struct-many`
|
|
127
|
+
* shape. Delete-only today (`op` must be `'delete'`). Unlike N separate
|
|
128
|
+
* `writeStruct(oid, 'delete')` calls, the server resolves every `oids` entry's
|
|
129
|
+
* offset against ONE shared file snapshot and applies them all in a single write
|
|
130
|
+
* — sound and CALLER-ORDER-INDEPENDENT (see `handleStructMany`'s doc comment,
|
|
131
|
+
* `vite-plugin-ui-oid.ts`): the caller does not need to sort `oids` into any
|
|
132
|
+
* particular order, source or otherwise. Same response shape as `writeStruct`
|
|
133
|
+
* (one `prevSource`/`newSource`/`prevSha`/`newSha` snapshot for the whole batch
|
|
134
|
+
* — one undo entry, not N). Optional: only a dev-server-backed implementation
|
|
135
|
+
* serves it; its absence is how `ReactWorldAuthoringAdapter` honestly degrades
|
|
136
|
+
* `structure.removeMany` to absent (the shell then falls back to
|
|
137
|
+
* `deleteSelection`'s per-id loop, unchanged).
|
|
138
|
+
*/
|
|
139
|
+
writeStructMany?(
|
|
140
|
+
oids: readonly string[],
|
|
141
|
+
op: string,
|
|
142
|
+
): Promise<{
|
|
143
|
+
changed: boolean;
|
|
144
|
+
error?: string;
|
|
145
|
+
file?: string;
|
|
146
|
+
prevSource?: string;
|
|
147
|
+
newSource?: string;
|
|
148
|
+
prevSha?: string;
|
|
149
|
+
newSha?: string;
|
|
150
|
+
}>;
|
|
151
|
+
/**
|
|
152
|
+
* D-1 — the checksum-guarded whole-file restore: the undo/redo inverse for a
|
|
153
|
+
* structural edit. Writes `source` to `file` ONLY if the file's CURRENT
|
|
154
|
+
* content hashes (sha256) to `ifMatchSha`; refuses — `restored: false`,
|
|
155
|
+
* NEVER writes — otherwise (the file changed out from under the timeline
|
|
156
|
+
* since, e.g. a hand-edit, or an out-of-order restore). The caller never
|
|
157
|
+
* computes a hash itself; it only echoes back one `writeStruct` already
|
|
158
|
+
* handed it (`prevSha`/`newSha`) — see that method's doc comment. Optional:
|
|
159
|
+
* only a dev-server-backed implementation can serve it — its absence is how
|
|
160
|
+
* a caller without whole-file-restore support (a legacy mock, a future
|
|
161
|
+
* non-dev-server tier) honestly degrades a structural op to "not undoable"
|
|
162
|
+
* instead of assuming a restore path that isn't there.
|
|
163
|
+
*/
|
|
164
|
+
restoreSource?(
|
|
165
|
+
file: string,
|
|
166
|
+
source: string,
|
|
167
|
+
ifMatchSha: string,
|
|
168
|
+
): Promise<{ restored: boolean; sha?: string; error?: string }>;
|
|
169
|
+
/** The whole OID → source-location index — the `/__ui-source/index` shape.
|
|
170
|
+
* Optional: only a dev-server-backed implementation can serve it. */
|
|
171
|
+
index?(): Promise<Record<string, OidEntry>>;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
async function postJson<T>(url: string, body: unknown): Promise<T> {
|
|
175
|
+
const res = await fetch(url, {
|
|
176
|
+
method: 'POST',
|
|
177
|
+
headers: { 'Content-Type': 'application/json' },
|
|
178
|
+
body: JSON.stringify(body),
|
|
179
|
+
});
|
|
180
|
+
return (await res.json()) as T;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/** Wraps the EXISTING `/__ui-source/write` + `/__ui-source/struct` dev-server
|
|
184
|
+
* endpoints (see `vite-plugin-ui-oid.ts`) — the dev-server-backed tier. */
|
|
185
|
+
export function createHttpSourceWriteBackend(): SourceWriteBackend {
|
|
186
|
+
return {
|
|
187
|
+
writeStyle: (oid, prop, value) => postJson('/__ui-source/write', { oid, prop, value }),
|
|
188
|
+
// D-A3: the removal sentinel — same endpoint, `value: null`.
|
|
189
|
+
removeStyle: (oid, prop) => postJson('/__ui-source/write', { oid, prop, value: null }),
|
|
190
|
+
writeCss: (file, selector, prop, value) =>
|
|
191
|
+
postJson('/__ui-source/css', { file, selector, prop, value }),
|
|
192
|
+
writeText: (oid, text) => postJson('/__ui-source/text', { oid, text }),
|
|
193
|
+
writeProp: (oid, prop, value) => postJson('/__ui-source/prop', { oid, prop, value }),
|
|
194
|
+
writeStruct: (oid, op, opts) => postJson('/__ui-source/struct', { oid, op, ...opts }),
|
|
195
|
+
writeStructMany: (oids, op) => postJson('/__ui-source/struct-many', { oids, op }),
|
|
196
|
+
restoreSource: (file, source, ifMatchSha) =>
|
|
197
|
+
postJson('/__ui-source/restore', { file, source, ifMatchSha }),
|
|
198
|
+
index: async () => {
|
|
199
|
+
const res = await fetch('/__ui-source/index');
|
|
200
|
+
return (await res.json()) as Record<string, OidEntry>;
|
|
201
|
+
},
|
|
202
|
+
};
|
|
203
|
+
}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CSS property → Tailwind class converter (Cap 6 of the React visual-edit parity port,
|
|
3
|
+
* `docs/REACT-VISUAL-EDIT-PARITY.md`). A faithful port of `../../../visual-edit/tailwind-
|
|
4
|
+
* map.ts`: the ~30 grouped-inspector properties, using NAMED utilities where a keyword maps
|
|
5
|
+
* cleanly (`flex`, `justify-center`, `font-bold`, `rounded-full`, `border-2`) and arbitrary
|
|
6
|
+
* values (`w-[200px]`, `bg-[#059669]`) as the universal lossless fallback.
|
|
7
|
+
*
|
|
8
|
+
* This is the NAMED-utility converter — complementary to `writer.ts`'s `cssToUtilityClass`,
|
|
9
|
+
* which stays on the strictly-lossless arbitrary+type-hint scheme the source-write dedupe
|
|
10
|
+
* (`classGroup`) depends on. Use this when a human-readable named utility is preferred over
|
|
11
|
+
* round-trip-exact arbitrary values.
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/** Sanitize a CSS value for use inside Tailwind's `[...]` arbitrary brackets (no spaces;
|
|
15
|
+
* collapse `, ` → `,` first, e.g. `rgb(0, 0, 0)` → `rgb(0,_0,_0)`). */
|
|
16
|
+
function sanitize(val: string): string {
|
|
17
|
+
return val.replace(/,\s+/g, ',').replace(/\s+/g, '_');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/** Empty / non-meaningful values that shouldn't generate a class. */
|
|
21
|
+
function isEmpty(val: string): boolean {
|
|
22
|
+
return !val || val === 'normal' || val === 'auto' || val === 'none' || val === '';
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const DISPLAY_MAP: Record<string, string> = {
|
|
26
|
+
block: 'block',
|
|
27
|
+
flex: 'flex',
|
|
28
|
+
grid: 'grid',
|
|
29
|
+
inline: 'inline',
|
|
30
|
+
'inline-block': 'inline-block',
|
|
31
|
+
'inline-flex': 'inline-flex',
|
|
32
|
+
'inline-grid': 'inline-grid',
|
|
33
|
+
none: 'hidden',
|
|
34
|
+
contents: 'contents',
|
|
35
|
+
};
|
|
36
|
+
const FLEX_DIRECTION_MAP: Record<string, string> = {
|
|
37
|
+
row: 'flex-row',
|
|
38
|
+
column: 'flex-col',
|
|
39
|
+
'row-reverse': 'flex-row-reverse',
|
|
40
|
+
'column-reverse': 'flex-col-reverse',
|
|
41
|
+
};
|
|
42
|
+
const JUSTIFY_CONTENT_MAP: Record<string, string> = {
|
|
43
|
+
'flex-start': 'justify-start',
|
|
44
|
+
'flex-end': 'justify-end',
|
|
45
|
+
center: 'justify-center',
|
|
46
|
+
'space-between': 'justify-between',
|
|
47
|
+
'space-around': 'justify-around',
|
|
48
|
+
'space-evenly': 'justify-evenly',
|
|
49
|
+
start: 'justify-start',
|
|
50
|
+
end: 'justify-end',
|
|
51
|
+
stretch: 'justify-stretch',
|
|
52
|
+
};
|
|
53
|
+
const ALIGN_ITEMS_MAP: Record<string, string> = {
|
|
54
|
+
'flex-start': 'items-start',
|
|
55
|
+
'flex-end': 'items-end',
|
|
56
|
+
center: 'items-center',
|
|
57
|
+
baseline: 'items-baseline',
|
|
58
|
+
stretch: 'items-stretch',
|
|
59
|
+
start: 'items-start',
|
|
60
|
+
end: 'items-end',
|
|
61
|
+
};
|
|
62
|
+
const TEXT_ALIGN_MAP: Record<string, string> = {
|
|
63
|
+
left: 'text-left',
|
|
64
|
+
center: 'text-center',
|
|
65
|
+
right: 'text-right',
|
|
66
|
+
justify: 'text-justify',
|
|
67
|
+
start: 'text-start',
|
|
68
|
+
end: 'text-end',
|
|
69
|
+
};
|
|
70
|
+
const OVERFLOW_MAP: Record<string, string> = {
|
|
71
|
+
visible: 'overflow-visible',
|
|
72
|
+
hidden: 'overflow-hidden',
|
|
73
|
+
scroll: 'overflow-scroll',
|
|
74
|
+
auto: 'overflow-auto',
|
|
75
|
+
clip: 'overflow-clip',
|
|
76
|
+
};
|
|
77
|
+
const BORDER_STYLE_MAP: Record<string, string> = {
|
|
78
|
+
none: 'border-none',
|
|
79
|
+
solid: 'border-solid',
|
|
80
|
+
dashed: 'border-dashed',
|
|
81
|
+
dotted: 'border-dotted',
|
|
82
|
+
double: 'border-double',
|
|
83
|
+
hidden: 'border-hidden',
|
|
84
|
+
};
|
|
85
|
+
const FONT_WEIGHT_MAP: Record<string, string> = {
|
|
86
|
+
'100': 'font-thin',
|
|
87
|
+
'200': 'font-extralight',
|
|
88
|
+
'300': 'font-light',
|
|
89
|
+
'400': 'font-normal',
|
|
90
|
+
'500': 'font-medium',
|
|
91
|
+
'600': 'font-semibold',
|
|
92
|
+
'700': 'font-bold',
|
|
93
|
+
'800': 'font-extrabold',
|
|
94
|
+
'900': 'font-black',
|
|
95
|
+
normal: 'font-normal',
|
|
96
|
+
bold: 'font-bold',
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
type Converter = (value: string) => string;
|
|
100
|
+
const arb =
|
|
101
|
+
(prefix: string): Converter =>
|
|
102
|
+
(v) =>
|
|
103
|
+
isEmpty(v) ? '' : `${prefix}-[${sanitize(v)}]`;
|
|
104
|
+
|
|
105
|
+
/** camelCase CSS property → a Tailwind-class converter (empty string ⇒ no class). */
|
|
106
|
+
const converters: Record<string, Converter> = {
|
|
107
|
+
display: (v) => DISPLAY_MAP[v] ?? '',
|
|
108
|
+
flexDirection: (v) => FLEX_DIRECTION_MAP[v] ?? '',
|
|
109
|
+
justifyContent: (v) => JUSTIFY_CONTENT_MAP[v] ?? '',
|
|
110
|
+
alignItems: (v) => ALIGN_ITEMS_MAP[v] ?? '',
|
|
111
|
+
gap: arb('gap'),
|
|
112
|
+
width: arb('w'),
|
|
113
|
+
height: arb('h'),
|
|
114
|
+
minWidth: arb('min-w'),
|
|
115
|
+
minHeight: arb('min-h'),
|
|
116
|
+
maxWidth: (v) => (v === 'none' ? 'max-w-none' : arb('max-w')(v)),
|
|
117
|
+
maxHeight: (v) => (v === 'none' ? 'max-h-none' : arb('max-h')(v)),
|
|
118
|
+
marginTop: (v) => `mt-[${sanitize(v)}]`,
|
|
119
|
+
marginRight: (v) => `mr-[${sanitize(v)}]`,
|
|
120
|
+
marginBottom: (v) => `mb-[${sanitize(v)}]`,
|
|
121
|
+
marginLeft: (v) => `ml-[${sanitize(v)}]`,
|
|
122
|
+
paddingTop: (v) => `pt-[${sanitize(v)}]`,
|
|
123
|
+
paddingRight: (v) => `pr-[${sanitize(v)}]`,
|
|
124
|
+
paddingBottom: (v) => `pb-[${sanitize(v)}]`,
|
|
125
|
+
paddingLeft: (v) => `pl-[${sanitize(v)}]`,
|
|
126
|
+
fontSize: arb('text'),
|
|
127
|
+
fontWeight: (v) => FONT_WEIGHT_MAP[v] ?? (isEmpty(v) ? '' : `font-[${sanitize(v)}]`),
|
|
128
|
+
lineHeight: arb('leading'),
|
|
129
|
+
textAlign: (v) => TEXT_ALIGN_MAP[v] ?? '',
|
|
130
|
+
color: (v) => namedColor('text', v) ?? arb('text')(v),
|
|
131
|
+
backgroundColor: (v) => namedColor('bg', v) ?? arb('bg')(v),
|
|
132
|
+
borderColor: (v) => namedColor('border', v) ?? arb('border')(v),
|
|
133
|
+
borderWidth: (v) => BORDER_WIDTH_MAP[v] ?? (isEmpty(v) ? '' : `border-[${sanitize(v)}]`),
|
|
134
|
+
borderStyle: (v) => BORDER_STYLE_MAP[v] ?? '',
|
|
135
|
+
borderRadius: (v) =>
|
|
136
|
+
v === '0' || v === '0px'
|
|
137
|
+
? 'rounded-none'
|
|
138
|
+
: v === '9999px' || v === '100%'
|
|
139
|
+
? 'rounded-full'
|
|
140
|
+
: arb('rounded')(v),
|
|
141
|
+
overflow: (v) => OVERFLOW_MAP[v] ?? '',
|
|
142
|
+
opacity: (v) => (v === '1' ? 'opacity-100' : v === '0' ? 'opacity-0' : arb('opacity')(v)),
|
|
143
|
+
boxShadow: (v) => (v === 'none' ? 'shadow-none' : arb('shadow')(v)),
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
const BORDER_WIDTH_MAP: Record<string, string> = {
|
|
147
|
+
'0': 'border-0',
|
|
148
|
+
'0px': 'border-0',
|
|
149
|
+
'1px': 'border',
|
|
150
|
+
'2px': 'border-2',
|
|
151
|
+
'4px': 'border-4',
|
|
152
|
+
'8px': 'border-8',
|
|
153
|
+
};
|
|
154
|
+
|
|
155
|
+
/** The few keyword colors Tailwind names directly (else the caller falls back to arbitrary). */
|
|
156
|
+
function namedColor(prefix: string, v: string): string | null {
|
|
157
|
+
if (v === 'transparent') return `${prefix}-transparent`;
|
|
158
|
+
if (v === 'inherit') return `${prefix}-inherit`;
|
|
159
|
+
if (v === 'currentColor' || v === 'currentcolor') return `${prefix}-current`;
|
|
160
|
+
return null;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/** Convert a single CSS `prop:value` to a Tailwind class (`''` if unmapped/empty). */
|
|
164
|
+
export function cssToTailwindClass(prop: string, value: string): string {
|
|
165
|
+
return converters[prop]?.(value.trim()) ?? '';
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/** Convert a record of CSS changes to a space-separated Tailwind class string. */
|
|
169
|
+
export function cssChangesToTailwindClasses(changes: Record<string, string>): string {
|
|
170
|
+
return Object.entries(changes)
|
|
171
|
+
.map(([prop, value]) => cssToTailwindClass(prop, value))
|
|
172
|
+
.filter(Boolean)
|
|
173
|
+
.join(' ');
|
|
174
|
+
}
|