fix(canvas): disabled module gating + toolbar reorganization
CI/CD / deploy (push) Failing after 3m4s
Details
CI/CD / deploy (push) Failing after 3m4s
Details
- Remove MODULE_BADGES fallback in tab-bar add-menu (show "Loading rApps..." instead of leaking all modules) - Block ?tool= URL param from spawning shapes for disabled modules - Add disabled-module overlay on existing canvas shapes (grayed out + "Module disabled" badge) - Guard newShape() against creating shapes for disabled modules - Reorganize toolbar from 10 groups to 9 category-aligned groups: Write, Embed (core 4), Communicate, Plan, Decide, Spend, Create, AI, Record - Eliminate duplicate "Connect" groups, slim mega "Embed" group, merge "Travel" into "Plan" Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
f1f63ca142
commit
2d0ca98ae6
|
|
@ -476,15 +476,11 @@ export class RStackTabBar extends HTMLElement {
|
|||
#renderAddMenu(): string {
|
||||
const existingModuleIds = new Set(this.#layers.map(l => l.moduleId));
|
||||
|
||||
// Use server module list if available, fall back to MODULE_BADGES keys
|
||||
const allModules: Array<{ id: string; name: string; icon: string; description: string }> =
|
||||
this.#modules.length > 0
|
||||
? this.#modules
|
||||
: Object.keys(MODULE_BADGES)
|
||||
.map(id => ({ id, name: id, icon: "", description: "" }));
|
||||
// Only use server module list — never fall back to MODULE_BADGES (leaks disabled modules)
|
||||
const allModules = this.#modules;
|
||||
|
||||
if (allModules.length === 0) {
|
||||
return `<div class="add-menu" id="add-menu"><div class="add-menu-empty">No rApps available</div></div>`;
|
||||
return `<div class="add-menu" id="add-menu"><div class="add-menu-empty">Loading rApps\u2026</div></div>`;
|
||||
}
|
||||
|
||||
let html = "";
|
||||
|
|
|
|||
|
|
@ -153,6 +153,26 @@
|
|||
cursor: default;
|
||||
}
|
||||
|
||||
/* Disabled-module overlay on canvas shapes */
|
||||
[data-module-disabled] {
|
||||
position: relative;
|
||||
opacity: 0.4;
|
||||
pointer-events: none !important;
|
||||
filter: grayscale(0.6);
|
||||
}
|
||||
[data-module-disabled]::after {
|
||||
content: "Module disabled";
|
||||
position: absolute;
|
||||
top: 4px; right: 4px;
|
||||
background: rgba(0,0,0,0.7);
|
||||
color: #fff;
|
||||
font-size: 11px;
|
||||
padding: 2px 6px;
|
||||
border-radius: 4px;
|
||||
pointer-events: none;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
/* Picker modal — inline replacement for browser prompt() */
|
||||
.picker-modal-overlay {
|
||||
position: fixed; inset: 0; z-index: 9999;
|
||||
|
|
@ -1985,42 +2005,18 @@
|
|||
</div>
|
||||
|
||||
<div id="toolbar">
|
||||
<!-- 1. Note -->
|
||||
<!-- 1. Write -->
|
||||
<div class="toolbar-group">
|
||||
<button class="toolbar-group-toggle" title="Note"><span class="tg-icon">📝</span><span class="tg-label">Note</span></button>
|
||||
<button class="toolbar-group-toggle" title="Write"><span class="tg-icon">📝</span><span class="tg-label">Write</span></button>
|
||||
<div class="toolbar-dropdown">
|
||||
<div class="toolbar-dropdown-header">Note</div>
|
||||
<div class="toolbar-dropdown-header">Write</div>
|
||||
<button id="new-markdown" title="New Blank Note">📝 Blank Note</button>
|
||||
<button id="from-rnotes" title="From rNotes">📋 From rNotes</button>
|
||||
<button id="new-slide" title="New Slide">🎞️ Slide</button>
|
||||
<button id="from-rnotes" title="From rNotes" data-requires-module="rnotes">📋 From rNotes</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 2. Connect -->
|
||||
<div class="toolbar-group">
|
||||
<button class="toolbar-group-toggle" title="Connect"><span class="tg-icon">🤝</span><span class="tg-label">Connect</span></button>
|
||||
<div class="toolbar-dropdown">
|
||||
<div class="toolbar-dropdown-header">Connect</div>
|
||||
<button id="new-chat" title="New Chat">💬 Chat</button>
|
||||
<button id="embed-meets" title="rMeets" data-requires-module="rmeets">📹 rMeets</button>
|
||||
<button id="new-record" title="Record" class="toolbar-disabled">🔴 Record</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 3. Media -->
|
||||
<div class="toolbar-group">
|
||||
<button class="toolbar-group-toggle" title="Media"><span class="tg-icon">🎵</span><span class="tg-label">Media</span></button>
|
||||
<div class="toolbar-dropdown">
|
||||
<div class="toolbar-dropdown-header">Media</div>
|
||||
<button id="new-transcription" title="Transcribe">🎤 Transcribe</button>
|
||||
<button id="new-stream" title="Stream" class="toolbar-disabled">📡 Stream</button>
|
||||
<button id="new-piano" title="Piano">🎹 Piano</button>
|
||||
<button id="embed-tube" title="Embed rTube" data-requires-module="rtube">🎬 rTube</button>
|
||||
<button id="embed-photos" title="Embed rPhotos" data-requires-module="rphotos">📸 rPhotos</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 4. Embed -->
|
||||
<!-- 2. Embed (core items only) -->
|
||||
<div class="toolbar-group">
|
||||
<button class="toolbar-group-toggle" title="Embed"><span class="tg-icon">🔗</span><span class="tg-label">Embed</span></button>
|
||||
<div class="toolbar-dropdown">
|
||||
|
|
@ -2029,32 +2025,92 @@
|
|||
<button id="new-image" title="Image">🖼️ Image</button>
|
||||
<button id="new-bookmark" title="Bookmark">🔖 Bookmark</button>
|
||||
<button id="new-google-item" title="Google">📎 Google</button>
|
||||
<button id="new-map" title="Map" data-requires-module="rmaps">🗺️ Map</button>
|
||||
<button id="new-social-post" title="Social Post" data-requires-module="rsocials">📱 Social Post</button>
|
||||
<button id="embed-notes" title="Embed rNotes" data-requires-module="rnotes">📝 rNotes</button>
|
||||
<button id="embed-books" title="Embed rBooks" data-requires-module="rbooks">📚 rBooks</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 3. Communicate -->
|
||||
<div class="toolbar-group">
|
||||
<button class="toolbar-group-toggle" title="Communicate"><span class="tg-icon">💬</span><span class="tg-label">Communicate</span></button>
|
||||
<div class="toolbar-dropdown">
|
||||
<div class="toolbar-dropdown-header">Communicate</div>
|
||||
<button id="new-chat" title="New Chat">💬 Chat</button>
|
||||
<button id="embed-meets" title="rMeets" data-requires-module="rmeets">📹 rMeets</button>
|
||||
<button id="embed-forum" title="Embed rForum" data-requires-module="rforum">💬 rForum</button>
|
||||
<button id="embed-inbox" title="Embed rInbox" data-requires-module="rinbox">📧 rInbox</button>
|
||||
<button id="embed-network" title="Embed rNetwork" data-requires-module="rnetwork">🌍 rNetwork</button>
|
||||
<button id="new-social-post" title="Social Post" data-requires-module="rsocials">📱 Social Post</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 4. Plan -->
|
||||
<div class="toolbar-group">
|
||||
<button class="toolbar-group-toggle" title="Plan"><span class="tg-icon">📅</span><span class="tg-label">Plan</span></button>
|
||||
<div class="toolbar-dropdown">
|
||||
<div class="toolbar-dropdown-header">Plan</div>
|
||||
<button id="new-calendar" title="Calendar" data-requires-module="rcal">📅 rCal</button>
|
||||
<button id="new-map" title="Map" data-requires-module="rmaps">🗺️ Map</button>
|
||||
<button id="new-itinerary" title="Itinerary" data-requires-module="rtrips">🗓️ Itinerary</button>
|
||||
<button id="new-destination" title="Destination" data-requires-module="rtrips">📍 Destination</button>
|
||||
<button id="new-budget" title="Budget" data-requires-module="rtrips">💰 Budget</button>
|
||||
<button id="new-packing-list" title="Packing List" data-requires-module="rtrips">🎒 Packing List</button>
|
||||
<button id="new-booking" title="Booking" data-requires-module="rtrips">✈️ Booking</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 5. Decide -->
|
||||
<div class="toolbar-group">
|
||||
<button class="toolbar-group-toggle" title="Decide"><span class="tg-icon">☑</span><span class="tg-label">Decide</span></button>
|
||||
<div class="toolbar-dropdown">
|
||||
<div class="toolbar-dropdown-header">Decide</div>
|
||||
<button id="new-choice-vote" title="Poll" data-requires-module="rchoices">☑ Poll</button>
|
||||
<button id="new-choice-rank" title="Ranking" data-requires-module="rchoices">📊 Ranking</button>
|
||||
<button id="new-choice-spider" title="Scoring" data-requires-module="rchoices">🕸 Scoring</button>
|
||||
<button id="new-spider-3d" title="3D Spider" data-requires-module="rchoices">📊 3D Spider</button>
|
||||
<button id="new-conviction" title="Conviction" data-requires-module="rchoices">⏳ Conviction</button>
|
||||
<button id="embed-vote" title="Embed rVote" data-requires-module="rvote">🗳️ rVote</button>
|
||||
<button id="new-commitment-pool" title="Commitment Pool" data-requires-module="rtime">🧺 Commitments</button>
|
||||
<button id="new-task-request" title="Task Request" data-requires-module="rtime">📋 Task Request</button>
|
||||
<button id="new-multisig-email" title="Multi-Sig Email">✉️ Multi-Sig Email</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 6. Spend -->
|
||||
<div class="toolbar-group">
|
||||
<button class="toolbar-group-toggle" title="Spend"><span class="tg-icon">💰</span><span class="tg-label">Spend</span></button>
|
||||
<div class="toolbar-dropdown">
|
||||
<div class="toolbar-dropdown-header">Spend</div>
|
||||
<button id="embed-wallet" title="rWallet" data-requires-module="rwallet">💰 rWallet</button>
|
||||
<button id="embed-flows" title="rFlows" data-requires-module="rflows">🌊 rFlows</button>
|
||||
<button id="new-tx-builder" title="Transaction Builder" data-requires-module="rwallet">🔐 Tx Builder</button>
|
||||
<button id="new-token" title="Token" data-requires-module="rwallet">🪙 Token</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 7. Create -->
|
||||
<div class="toolbar-group">
|
||||
<button class="toolbar-group-toggle" title="Create"><span class="tg-icon">🛠️</span><span class="tg-label">Create</span></button>
|
||||
<div class="toolbar-dropdown">
|
||||
<div class="toolbar-dropdown-header">Create</div>
|
||||
<button id="new-drawfast" title="Drawfast">✏️ Drawfast</button>
|
||||
<button id="new-blender" title="3D Blender">🧊 Blender</button>
|
||||
<button id="new-freecad" title="FreeCAD">📐 FreeCAD</button>
|
||||
<button id="new-kicad" title="KiCAD PCB">🔌 KiCAD</button>
|
||||
<button id="new-splat" title="3D Splat" data-requires-module="rsplat">🔮 3D Splat</button>
|
||||
<button id="new-scribus" title="Scribus DTP" data-requires-module="rdesign">🎨 Scribus</button>
|
||||
<button id="embed-swag" title="Embed rSwag" data-requires-module="rswag">🎨 rSwag</button>
|
||||
<button id="embed-pubs" title="Embed rPubs" data-requires-module="rpubs">📖 rPubs</button>
|
||||
<button id="embed-books" title="Embed rBooks" data-requires-module="rbooks">📚 rBooks</button>
|
||||
<button id="embed-photos" title="Embed rPhotos" data-requires-module="rphotos">📸 rPhotos</button>
|
||||
<button id="embed-tube" title="Embed rTube" data-requires-module="rtube">🎬 rTube</button>
|
||||
<button id="embed-files" title="Embed rFiles" data-requires-module="rfiles">📁 rFiles</button>
|
||||
<button id="embed-notes" title="Embed rNotes" data-requires-module="rnotes">📝 rNotes</button>
|
||||
<button id="embed-tasks" title="Embed rTasks" data-requires-module="rtasks">📋 rTasks</button>
|
||||
<button id="embed-cart" title="Embed rCart" data-requires-module="rcart">🛒 rCart</button>
|
||||
<button id="embed-data" title="Embed rData" data-requires-module="rdata">📊 rData</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 5. Connect -->
|
||||
<div class="toolbar-group">
|
||||
<button class="toolbar-group-toggle" title="Connect"><span class="tg-icon">🔌</span><span class="tg-label">Connect</span></button>
|
||||
<div class="toolbar-dropdown">
|
||||
<div class="toolbar-dropdown-header">Connect</div>
|
||||
<button id="new-calendar" title="Calendar" data-requires-module="rcal">📅 rCal</button>
|
||||
<button id="embed-inbox" title="Embed rInbox" data-requires-module="rinbox">📧 rInbox</button>
|
||||
<button id="embed-network" title="Embed rNetwork" data-requires-module="rnetwork">🌍 rNetwork</button>
|
||||
<button id="new-holon" title="Holon">🌐 Holon</button>
|
||||
<button id="new-holon-browser" title="Holon Browser">🔍 Holon Browser</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 6. AI (was 5) -->
|
||||
<!-- 8. AI -->
|
||||
<div class="toolbar-group">
|
||||
<button class="toolbar-group-toggle" title="AI"><span class="tg-icon">🤖</span><span class="tg-label">AI</span></button>
|
||||
<div class="toolbar-dropdown">
|
||||
|
|
@ -2068,61 +2124,17 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 6. Create -->
|
||||
<!-- 9. Record -->
|
||||
<div class="toolbar-group">
|
||||
<button class="toolbar-group-toggle" title="Create"><span class="tg-icon">🛠️</span><span class="tg-label">Create</span></button>
|
||||
<button class="toolbar-group-toggle" title="Record"><span class="tg-icon">🎙️</span><span class="tg-label">Record</span></button>
|
||||
<div class="toolbar-dropdown">
|
||||
<div class="toolbar-dropdown-header">Create</div>
|
||||
<button id="new-splat" title="3D Splat" data-requires-module="rsplat">🔮 3D Splat</button>
|
||||
<button id="new-blender" title="3D Blender">🧊 Blender</button>
|
||||
<button id="new-drawfast" title="Drawfast">✏️ Drawfast</button>
|
||||
<button id="new-freecad" title="FreeCAD">📐 FreeCAD</button>
|
||||
<button id="new-kicad" title="KiCAD PCB">🔌 KiCAD</button>
|
||||
<button id="new-scribus" title="Scribus DTP" data-requires-module="rdesign">🎨 Scribus</button>
|
||||
<button id="embed-swag" title="Embed rSwag" data-requires-module="rswag">🎨 rSwag</button>
|
||||
<button id="embed-pubs" title="Embed rPubs" data-requires-module="rpubs">📖 rPubs</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 7. Decide -->
|
||||
<div class="toolbar-group">
|
||||
<button class="toolbar-group-toggle" title="Decide"><span class="tg-icon">📊</span><span class="tg-label">Decide</span></button>
|
||||
<div class="toolbar-dropdown">
|
||||
<div class="toolbar-dropdown-header">Decide</div>
|
||||
<button id="new-choice-vote" title="Poll" data-requires-module="rchoices">☑ Poll</button>
|
||||
<button id="new-choice-rank" title="Ranking" data-requires-module="rchoices">📊 Ranking</button>
|
||||
<button id="new-choice-spider" title="Scoring" data-requires-module="rchoices">🕸 Scoring</button>
|
||||
<button id="new-spider-3d" title="3D Spider" data-requires-module="rchoices">📊 3D Spider</button>
|
||||
<button id="new-conviction" title="Conviction" data-requires-module="rchoices">⏳ Conviction</button>
|
||||
<button id="new-token" title="Token" data-requires-module="rwallet">🪙 Token</button>
|
||||
<button id="new-commitment-pool" title="Commitment Pool" data-requires-module="rtime">🧺 Commitments</button>
|
||||
<button id="new-task-request" title="Task Request" data-requires-module="rtime">📋 Task Request</button>
|
||||
<button id="new-multisig-email" title="Multi-Sig Email">✉️ Multi-Sig Email</button>
|
||||
<button id="embed-vote" title="Embed rVote" data-requires-module="rvote">🗳️ rVote</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 8. Spend -->
|
||||
<div class="toolbar-group">
|
||||
<button class="toolbar-group-toggle" title="Spend"><span class="tg-icon">💰</span><span class="tg-label">Spend</span></button>
|
||||
<div class="toolbar-dropdown">
|
||||
<div class="toolbar-dropdown-header">Spend</div>
|
||||
<button id="embed-wallet" title="rWallet" data-requires-module="rwallet">💰 rWallet</button>
|
||||
<button id="embed-flows" title="rFlows" data-requires-module="rflows">🌊 rFlows</button>
|
||||
<button id="new-tx-builder" title="Transaction Builder" data-requires-module="rwallet">🔐 Tx Builder</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 9. Travel -->
|
||||
<div class="toolbar-group">
|
||||
<button class="toolbar-group-toggle" title="Travel"><span class="tg-icon">✈️</span><span class="tg-label">Travel</span></button>
|
||||
<div class="toolbar-dropdown">
|
||||
<div class="toolbar-dropdown-header">Travel</div>
|
||||
<button id="new-itinerary" title="Itinerary" data-requires-module="rtrips">🗓️ Itinerary</button>
|
||||
<button id="new-destination" title="Destination" data-requires-module="rtrips">📍 Destination</button>
|
||||
<button id="new-budget" title="Budget" data-requires-module="rtrips">💰 Budget</button>
|
||||
<button id="new-packing-list" title="Packing List" data-requires-module="rtrips">🎒 Packing List</button>
|
||||
<button id="new-booking" title="Booking" data-requires-module="rtrips">✈️ Booking</button>
|
||||
<div class="toolbar-dropdown-header">Record</div>
|
||||
<button id="new-transcription" title="Transcribe">🎤 Transcribe</button>
|
||||
<button id="new-piano" title="Piano">🎹 Piano</button>
|
||||
<button id="new-holon" title="Holon">🌐 Holon</button>
|
||||
<button id="new-holon-browser" title="Holon Browser">🔍 Holon Browser</button>
|
||||
<button id="new-record" title="Record" class="toolbar-disabled">🔴 Record</button>
|
||||
<button id="new-stream" title="Stream" class="toolbar-disabled">📡 Stream</button>
|
||||
</div>
|
||||
</div>
|
||||
<button id="toolbar-collapse" title="Minimize toolbar"><svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><line x1="6" y1="18" x2="18" y2="18"/></svg></button>
|
||||
|
|
@ -2587,6 +2599,8 @@
|
|||
const cls = customElements.get("folk-task-request");
|
||||
if (cls?.setEnabledModules) cls.setEnabledModules(enabledIds);
|
||||
});
|
||||
// Overlay disabled-module shapes on canvas
|
||||
syncCanvasShapeModuleStates(enabledIds);
|
||||
}).catch(() => {});
|
||||
|
||||
// React to runtime module toggling from app switcher
|
||||
|
|
@ -2609,6 +2623,9 @@
|
|||
const FolkTaskRequest = customElements.get("folk-task-request");
|
||||
if (FolkTaskRequest?.setEnabledModules) FolkTaskRequest.setEnabledModules(enabledModules);
|
||||
|
||||
// Update disabled-module overlays on canvas shapes
|
||||
syncCanvasShapeModuleStates(enabledModules);
|
||||
|
||||
document.querySelectorAll("[data-requires-module]").forEach(el => {
|
||||
el.style.display = enabledSet.has(el.dataset.requiresModule) ? "" : "none";
|
||||
});
|
||||
|
|
@ -3963,6 +3980,52 @@ Use real coordinates, YYYY-MM-DD dates, ISO currency codes. Ask clarifying quest
|
|||
});
|
||||
}
|
||||
|
||||
// Map shape tag → required module (for gating disabled-module shapes)
|
||||
const SHAPE_TO_MODULE = {
|
||||
"folk-map": "rmaps",
|
||||
"folk-calendar": "rcal",
|
||||
"folk-social-post": "rsocials",
|
||||
"folk-splat": "rsplat",
|
||||
"folk-design-agent": "rdesign",
|
||||
"folk-choice-vote": "rchoices",
|
||||
"folk-choice-rank": "rchoices",
|
||||
"folk-choice-spider": "rchoices",
|
||||
"folk-spider-3d": "rchoices",
|
||||
"folk-choice-conviction": "rchoices",
|
||||
"folk-token-mint": "rwallet",
|
||||
"folk-token-ledger": "rwallet",
|
||||
"folk-transaction-builder": "rwallet",
|
||||
"folk-commitment-pool": "rtime",
|
||||
"folk-task-request": "rtime",
|
||||
"folk-gov-binary": "rvote",
|
||||
"folk-gov-threshold": "rvote",
|
||||
"folk-itinerary": "rtrips",
|
||||
"folk-destination": "rtrips",
|
||||
"folk-budget": "rtrips",
|
||||
"folk-packing-list": "rtrips",
|
||||
"folk-booking": "rtrips",
|
||||
"folk-video-chat": "rmeets",
|
||||
// folk-rapp shapes are gated separately via FolkRApp.setEnabledModules
|
||||
};
|
||||
|
||||
/** Toggle data-module-disabled on existing canvas shapes based on enabled module list */
|
||||
function syncCanvasShapeModuleStates(enabledIds) {
|
||||
if (!enabledIds) return;
|
||||
const enabledSet = new Set(enabledIds);
|
||||
const canvasEl = document.getElementById("canvas-content") || document.getElementById("canvas");
|
||||
if (!canvasEl) return;
|
||||
for (const shape of canvasEl.children) {
|
||||
const tag = shape.tagName?.toLowerCase();
|
||||
const reqMod = SHAPE_TO_MODULE[tag];
|
||||
if (!reqMod) continue;
|
||||
if (enabledSet.has(reqMod)) {
|
||||
shape.removeAttribute("data-module-disabled");
|
||||
} else {
|
||||
shape.setAttribute("data-module-disabled", reqMod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Default dimensions for each shape type
|
||||
const SHAPE_DEFAULTS = {
|
||||
"folk-markdown": { width: 300, height: 200 },
|
||||
|
|
@ -4226,6 +4289,13 @@ Use real coordinates, YYYY-MM-DD dates, ISO currency codes. Ask clarifying quest
|
|||
// atPosition: optional { x, y } in canvas coordinates — places shape centered there exactly.
|
||||
// Without atPosition, uses findFreePosition to auto-place without overlapping.
|
||||
function newShape(tagName, props = {}, atPosition) {
|
||||
// Block creating shapes for disabled modules
|
||||
const _reqMod = SHAPE_TO_MODULE[tagName];
|
||||
if (_reqMod && window.__rspaceEnabledModules &&
|
||||
!new Set(window.__rspaceEnabledModules).has(_reqMod)) {
|
||||
console.warn(`[Canvas] Blocked newShape("${tagName}") — module "${_reqMod}" is disabled`);
|
||||
return null;
|
||||
}
|
||||
const id = `shape-${Date.now()}-${++shapeCounter}`;
|
||||
const defaults = SHAPE_DEFAULTS[tagName] || { width: 300, height: 200 };
|
||||
|
||||
|
|
@ -5071,7 +5141,10 @@ Use real coordinates, YYYY-MM-DD dates, ISO currency codes. Ask clarifying quest
|
|||
|
||||
// Auto-spawn shape from ?tool= URL param (e.g. ?tool=folk-zine-gen)
|
||||
const toolParam = urlParams.get("tool");
|
||||
if (toolParam && shapeRegistry.has(toolParam)) {
|
||||
const _toolMod = toolParam && SHAPE_TO_MODULE[toolParam];
|
||||
const _toolAllowed = !_toolMod || !window.__rspaceEnabledModules ||
|
||||
new Set(window.__rspaceEnabledModules).has(_toolMod);
|
||||
if (toolParam && shapeRegistry.has(toolParam) && _toolAllowed) {
|
||||
const spawnToolShape = () => {
|
||||
newShape(toolParam);
|
||||
const cleanUrl = new URL(window.location.href);
|
||||
|
|
|
|||
Loading…
Reference in New Issue