diff --git a/plugin/BuildAdmin.luau b/plugin/BuildAdmin.luau index 457b5ac..267ac87 100644 --- a/plugin/BuildAdmin.luau +++ b/plugin/BuildAdmin.luau @@ -267,8 +267,11 @@ function BuildAdmin.applyType(instances: { Instance }, schema: any, all: { any } end -- The honest inverse of applyType: remove every known component tag, its attributes, and the --- engine's `_`-prefixed stamps. Returns { cleared }. -function BuildAdmin.clear(instances: { Instance }, all: { any }): any +-- engine's `_`-prefixed stamps. `extraTags` removes specific additional tags by name — the page +-- passes the unknown tags it just displayed, so its "Clear" button actually clears what the user +-- was shown. Tags are never removed speculatively: an unlisted tag may belong to another plugin. +-- Returns { cleared }. +function BuildAdmin.clear(instances: { Instance }, all: { any }, extraTags: { string }?): any local cleared = 0 for _, instance in instances do if not alive(instance) then @@ -282,6 +285,15 @@ function BuildAdmin.clear(instances: { Instance }, all: { any }): any touched = true end end + for _, tag in (extraTags or {}) :: { string } do + if CollectionService:HasTag(instance, tag) then + CollectionService:RemoveTag(instance, tag) + touched = true + end + end + if instance:GetAttribute(BOUND_ATTR) ~= nil then + touched = true + end stripEngineStamps(instance) if touched then cleared += 1 diff --git a/plugin/BuildAdminUi.luau b/plugin/BuildAdminUi.luau index bbdc021..d602e04 100644 --- a/plugin/BuildAdminUi.luau +++ b/plugin/BuildAdminUi.luau @@ -49,8 +49,11 @@ local function countAdvanced(specs: { any }): number end -- One clickable "what is this?" card. Ineligible components render dim and inert, with the reason. -local function chooserCard(schema: any, display: any, eligible: boolean, reason: string?, onPick): Frame - local panel = Theme.panel() +-- The CARD ITSELF is the button when it's pickable: a full-size button parented INTO a panel would +-- be laid out by the panel's UIListLayout as another row (no opt-out; ZIndex doesn't affect +-- layout), leaving the card body dead and the button spilling onto the next card. +local function chooserCard(schema: any, display: any, eligible: boolean, reason: string?, onPick): GuiObject + local panel: any = if eligible then Theme.panelButton() else Theme.panel() local title = Theme.label({ Size = UDim2.new(1, 0, 0, 20), Text = display.title, @@ -74,15 +77,7 @@ local function chooserCard(schema: any, display: any, eligible: boolean, reason: panel if eligible then - -- A transparent button over the whole card keeps the panel's styling but makes it clickable. - local hit = Theme.make("TextButton", { - Size = UDim2.fromScale(1, 1), - BackgroundTransparency = 1, - Text = "", - ZIndex = 3, - }) :: TextButton - hit.Parent = panel - hit.MouseButton1Click:Connect(function() + (panel :: TextButton).MouseButton1Click:Connect(function() onPick(schema) end) Theme.hover(panel, Theme.COLOR.PANEL, Theme.COLOR.PANEL_HOVER) @@ -160,12 +155,13 @@ function BuildAdminUi.mount(container: Frame, BuildAdmin: any, ContentAdmin: any end end - local function clearType(instances: { Instance }, all: { any }) - local res = actions.clear(instances, all) + local function clearType(instances: { Instance }, all: { any }, extraTags: { string }?) + local res = actions.clear(instances, all, extraTags) chooserOpen = false refresh() if typeof(res) == "table" then - say(`✓ cleared {res.cleared or 0} object(s)`) + local n = res.cleared or 0 + say(if n > 0 then `✓ cleared {n} object(s)` else "nothing to clear on that object") end end @@ -432,7 +428,8 @@ function BuildAdminUi.mount(container: Frame, BuildAdmin: any, ContentAdmin: any }) clearBtn.Parent = scroll clearBtn.MouseButton1Click:Connect(function() - clearType({ instance }, all) + -- Pass the unknown tags we just listed, so Clear removes exactly what was shown. + clearType({ instance }, all, id.unknownTags) end) end diff --git a/plugin/FieldRow.luau b/plugin/FieldRow.luau index 258656e..b04a1a2 100644 --- a/plugin/FieldRow.luau +++ b/plugin/FieldRow.luau @@ -140,18 +140,20 @@ function FieldRow.build(opts: any): Frame end if hasHelp then - Theme.label({ + -- `row` owns a UIListLayout, which overwrites child Position — so the indent under the + -- label column has to come from padding, not Position. + local help = Theme.label({ Size = UDim2.fromScale(1, 0), AutomaticSize = Enum.AutomaticSize.Y, - Position = UDim2.fromOffset(22, 0), Text = spec.help, TextColor3 = Theme.COLOR.DIM, TextWrapped = true, TextSize = 11, TextTruncate = Enum.TextTruncate.None, LayoutOrder = 2, - }).Parent = - row + }) + Theme.pad(22, 0, 0, 2).Parent = help + help.Parent = row end return row diff --git a/plugin/Theme.luau b/plugin/Theme.luau index 9dc560f..ec97616 100644 --- a/plugin/Theme.luau +++ b/plugin/Theme.luau @@ -171,6 +171,27 @@ function Theme.panel(): Frame }) :: Frame end +-- A CLICKABLE panel: identical styling to Theme.panel, but the card itself is the button. +-- Use this instead of parenting a full-size button "overlay" into a panel — the panel's own +-- UIListLayout lays out EVERY GuiObject child (there is no opt-out, and ZIndex doesn't change +-- layout), so such an "overlay" becomes another list row: the card body stops being clickable and +-- the oversized button spills onto whatever is rendered next. +function Theme.panelButton(): TextButton + return Theme.make("TextButton", { + BackgroundColor3 = Theme.COLOR.PANEL, + BorderSizePixel = 0, + Size = UDim2.fromScale(1, 0), + AutomaticSize = Enum.AutomaticSize.Y, + Text = "", + AutoButtonColor = false, -- Theme.hover owns the highlight, matching the other cards + }, { + Theme.corner(8), + Theme.stroke(), + Theme.pad(8, 8, 6, 8), + Theme.make("UIListLayout", { Padding = UDim.new(0, 2), SortOrder = Enum.SortOrder.LayoutOrder }), + }) :: TextButton +end + -- A small count/status pill (rail badges, entry badges). function Theme.badge(text: string, textColor: Color3?): TextLabel return Theme.make("TextLabel", { diff --git a/plugin/init.server.luau b/plugin/init.server.luau index f561824..bd2ed18 100644 --- a/plugin/init.server.luau +++ b/plugin/init.server.luau @@ -123,9 +123,9 @@ local buildActions = { return BuildAdmin.applyType(instances, schema, all) end) end, - clear = function(instances: { Instance }, all: { any }): any + clear = function(instances: { Instance }, all: { any }, extraTags: { string }?): any return record("Build: clear component", function() - return BuildAdmin.clear(instances, all) + return BuildAdmin.clear(instances, all, extraTags) end) end, setField = function(instance: Instance, spec: any, raw: any): any