diff --git a/.justfile b/.justfile index c8f7e05..e49acc8 100644 --- a/.justfile +++ b/.justfile @@ -46,6 +46,7 @@ _get-plugin-name: _prune: rm -rf {{ plugin_build / "**/*.spec.luau" }} rm -rf {{ plugin_build / "**/*.story.luau" }} + rm -rf {{ plugin_build / "**/*.storybook.luau" }} _build target output: -rm -rf {{ plugin_build }} diff --git a/plugin/src/components/ThemeDetails.luau b/plugin/src/components/ThemeDetails.luau index 22c4db1..3779199 100644 --- a/plugin/src/components/ThemeDetails.luau +++ b/plugin/src/components/ThemeDetails.luau @@ -3,10 +3,10 @@ local Sift = require("@pkg/Sift") local types = require("@root/types") local applyTheme = require("@root/applyTheme") local getLayoutOrder = require("./getLayoutOrder") +local ThemeLabel = require("./ThemeLabel") local useCallback = React.useCallback -local ACTION_BUTTON_WIDTH = 120 local PADDING = UDim.new(0, 8) export type Props = { @@ -58,68 +58,9 @@ local function ThemeDetails(providedProps: Props) AutomaticSize = Enum.AutomaticSize.Y, Size = UDim2.fromScale(1, 0), }, { - Layout = React.createElement("UIListLayout", { - SortOrder = Enum.SortOrder.LayoutOrder, - FillDirection = Enum.FillDirection.Horizontal, - VerticalAlignment = Enum.VerticalAlignment.Center, - }), - - Padding = React.createElement("UIPadding", { - PaddingTop = PADDING, - PaddingRight = PADDING, - PaddingBottom = PADDING, - PaddingLeft = PADDING, - }), - - Main = React.createElement("Frame", { - LayoutOrder = getLayoutOrder(), - Size = UDim2.fromScale(1, 0) - UDim2.fromOffset(ACTION_BUTTON_WIDTH, 0), - AutomaticSize = Enum.AutomaticSize.Y, - BackgroundTransparency = 1, - }, { - Layout = React.createElement("UIListLayout", { - SortOrder = Enum.SortOrder.LayoutOrder, - Padding = PADDING, - }), - - Name = React.createElement("TextLabel", { - LayoutOrder = getLayoutOrder(), - AutomaticSize = Enum.AutomaticSize.XY, - BackgroundTransparency = 1, - Text = theme.name, - TextSize = 16, - Font = Enum.Font.GothamMedium, - TextXAlignment = Enum.TextXAlignment.Left, - TextYAlignment = Enum.TextYAlignment.Top, - TextColor3 = Color3.fromRGB(255, 255, 255), - TextTruncate = Enum.TextTruncate.AtEnd, - }), - }), - - Action = React.createElement("TextButton", { - LayoutOrder = getLayoutOrder(), - Text = "Use Theme", - TextSize = 14, - TextColor3 = Color3.fromRGB(255, 255, 255), - BorderSizePixel = 0, - Font = Enum.Font.GothamMedium, - Size = UDim2.fromOffset(ACTION_BUTTON_WIDTH, 0), - AutomaticSize = Enum.AutomaticSize.Y, - BackgroundColor3 = Color3.fromRGB(143, 186, 86), - [React.Event.Activated] = function() - onApplyTheme(theme) - end, - }, { - Padding = React.createElement("UIPadding", { - PaddingTop = PADDING, - PaddingRight = PADDING, - PaddingBottom = PADDING, - PaddingLeft = PADDING, - }), - - Corner = React.createElement("UICorner", { - CornerRadius = PADDING, - }), + ThemeLabel = React.createElement(ThemeLabel, { + theme = theme, + onApplyTheme = onApplyTheme, }), }) end diff --git a/plugin/src/components/ThemeLabel.luau b/plugin/src/components/ThemeLabel.luau new file mode 100644 index 0000000..ae387f7 --- /dev/null +++ b/plugin/src/components/ThemeLabel.luau @@ -0,0 +1,150 @@ +local React = require("@pkg/React") +local types = require("@root/types") +local getLayoutOrder = require("./getLayoutOrder") +local getThemeColors = require("@root/getThemeColors") + +local useMemo = React.useMemo + +local ACTION_BUTTON_WIDTH = 120 +local PADDING = UDim.new(0, 8) +local NUM_PREVIEW_COLORS = 5 + +export type Props = { + theme: types.ExtensionTheme, + onApplyTheme: ((theme: types.ExtensionTheme) -> ())?, + LayoutOrder: number?, +} + +local function ThemeLabel(props: Props) + local previewedColors = useMemo(function() + local colors = getThemeColors(props.theme) + local elements = {} + local count = 0 + + for _, colorCode in colors.found do + local success, color = pcall(Color3.fromHex, colorCode) + if success then + elements[colorCode] = React.createElement("Frame", { + LayoutOrder = count, + BackgroundColor3 = color, + Size = UDim2.fromOffset(32, 32), + BorderSizePixel = 0, + }, { + BorderRadius = React.createElement("UICorner", { + CornerRadius = UDim.new(1, 0), + }), + }) + + count += 1 + if count == NUM_PREVIEW_COLORS then + break + end + end + end + + for i = 1, NUM_PREVIEW_COLORS do + local color = colors.found[i] + + if color then + elements[tostring(color)] = React.createElement("Frame", { + LayoutOrder = i, + BackgroundColor3 = color, + Size = UDim2.fromOffset(32, 32), + BorderSizePixel = 0, + }) + end + end + + return elements + end, { props.theme }) + + return React.createElement("Frame", { + LayoutOrder = props.LayoutOrder, + BackgroundTransparency = 1, + AutomaticSize = Enum.AutomaticSize.Y, + Size = UDim2.fromScale(1, 0), + }, { + Layout = React.createElement("UIListLayout", { + SortOrder = Enum.SortOrder.LayoutOrder, + FillDirection = Enum.FillDirection.Horizontal, + VerticalAlignment = Enum.VerticalAlignment.Center, + }), + + Padding = React.createElement("UIPadding", { + PaddingTop = PADDING, + PaddingRight = PADDING, + PaddingBottom = PADDING, + PaddingLeft = PADDING, + }), + + Main = React.createElement("Frame", { + LayoutOrder = getLayoutOrder(), + Size = UDim2.fromScale(1, 0) - UDim2.fromOffset(ACTION_BUTTON_WIDTH, 0), + AutomaticSize = Enum.AutomaticSize.Y, + BackgroundTransparency = 1, + }, { + Layout = React.createElement("UIListLayout", { + SortOrder = Enum.SortOrder.LayoutOrder, + Padding = PADDING, + }), + + Name = React.createElement("TextLabel", { + LayoutOrder = getLayoutOrder(), + AutomaticSize = Enum.AutomaticSize.XY, + BackgroundTransparency = 1, + Text = props.theme.name, + TextSize = 16, + Font = Enum.Font.GothamMedium, + TextXAlignment = Enum.TextXAlignment.Left, + TextYAlignment = Enum.TextYAlignment.Top, + TextColor3 = Color3.fromRGB(255, 255, 255), + TextTruncate = Enum.TextTruncate.AtEnd, + }), + + Colors = React.createElement("Frame", { + LayoutOrder = getLayoutOrder(), + Size = UDim2.fromScale(1, 0), + AutomaticSize = Enum.AutomaticSize.Y, + BackgroundTransparency = 1, + }, { + Layout = React.createElement("UIListLayout", { + SortOrder = Enum.SortOrder.LayoutOrder, + FillDirection = Enum.FillDirection.Horizontal, + Padding = PADDING, + }), + + PreviewColors = React.createElement(React.Fragment, {}, previewedColors), + }), + }), + + Action = React.createElement("TextButton", { + LayoutOrder = getLayoutOrder(), + Text = "Use Theme", + TextSize = 14, + TextColor3 = Color3.fromRGB(255, 255, 255), + BorderSizePixel = 0, + Font = Enum.Font.GothamMedium, + Size = UDim2.fromOffset(ACTION_BUTTON_WIDTH, 0), + AutomaticSize = Enum.AutomaticSize.Y, + BackgroundColor3 = Color3.fromRGB(143, 186, 86), + [React.Event.Activated] = function() + if props.onApplyTheme then + props.onApplyTheme(props.theme) + end + end, + }, { + Padding = React.createElement("UIPadding", { + PaddingTop = PADDING, + PaddingRight = PADDING, + PaddingBottom = PADDING, + PaddingLeft = PADDING, + }), + + Corner = React.createElement("UICorner", { + CornerRadius = PADDING, + }), + }), + }) +end + +return ThemeLabel diff --git a/plugin/src/components/ThemeLabel.story.luau b/plugin/src/components/ThemeLabel.story.luau new file mode 100644 index 0000000..fe88b85 --- /dev/null +++ b/plugin/src/components/ThemeLabel.story.luau @@ -0,0 +1,14 @@ +local React = require("@pkg/React") +local ThemeLabel = require("./ThemeLabel") +local themesSnapshot = require("@root/requests/snapshots/get-v1-themes") + +return { + story = function() + return React.createElement(ThemeLabel, { + theme = themesSnapshot[1], + onApplyTheme = function() + print("apply theme") + end, + }) + end, +} diff --git a/plugin/src/getThemeColors.luau b/plugin/src/getThemeColors.luau index 1211a45..c489343 100644 --- a/plugin/src/getThemeColors.luau +++ b/plugin/src/getThemeColors.luau @@ -5,14 +5,14 @@ local constants = require("@root/constants") local getScopeColors = require("@root/getScopeColors") local function getThemeColors(theme): { - found: { [string]: Color3 }, + found: { [string]: string }, missing: { string }, } local found = {} local missing = {} for studioName, vscodeColors in constants.ROBLOX_VSCODE_THEME_MAP do - local color: Color3 + local color: string for _, vscodeColor in vscodeColors do -- TODO: Some default themes like Dark+ have an "include" field, which