@rbxts/react-clean-ui 1.0.19 → 1.0.38

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.
Files changed (99) hide show
  1. package/out/Components/Chart/BarChart.d.ts +47 -0
  2. package/out/Components/Chart/BarChart.luau +880 -0
  3. package/out/Components/Chart/Pie.luau +12 -12
  4. package/out/Components/Chart/index.d.ts +1 -0
  5. package/out/Components/Chart/init.luau +3 -0
  6. package/out/Components/Input/Button.d.ts +9 -0
  7. package/out/Components/Input/Button.luau +155 -46
  8. package/out/Components/Input/Checkbox.luau +21 -5
  9. package/out/Components/Input/Increment.d.ts +11 -0
  10. package/out/Components/Input/Increment.luau +107 -0
  11. package/out/Components/Input/Increment.step.d.ts +1 -0
  12. package/out/Components/Input/Increment.step.luau +25 -0
  13. package/out/Components/Input/Input.d.ts +4 -3
  14. package/out/Components/Input/Input.luau +124 -17
  15. package/out/Components/Input/Input.validation.d.ts +3 -0
  16. package/out/Components/Input/Input.validation.luau +21 -0
  17. package/out/Components/Input/Select.d.ts +4 -3
  18. package/out/Components/Input/Select.luau +23 -18
  19. package/out/Components/Input/Slider.d.ts +1 -1
  20. package/out/Components/Input/Slider.luau +68 -34
  21. package/out/Components/Input/index.d.ts +1 -0
  22. package/out/Components/Input/init.luau +3 -0
  23. package/out/Components/Interaction/Toast.d.ts +1 -1
  24. package/out/Components/Interaction/Toast.luau +4 -4
  25. package/out/Components/Interaction/Tooltip.d.ts +1 -1
  26. package/out/Components/Interaction/Tooltip.luau +8 -1
  27. package/out/Components/Layout/Accordion.d.ts +34 -0
  28. package/out/Components/Layout/Accordion.luau +431 -0
  29. package/out/Components/Layout/Container.d.ts +4 -2
  30. package/out/Components/Layout/Container.luau +32 -7
  31. package/out/Components/Layout/Draggable.luau +1 -1
  32. package/out/Components/Layout/Fieldset.d.ts +1 -1
  33. package/out/Components/Layout/FlexItem.d.ts +2 -1
  34. package/out/Components/Layout/FlexItem.luau +1 -0
  35. package/out/Components/Layout/HStack.d.ts +2 -1
  36. package/out/Components/Layout/HStack.luau +1 -2
  37. package/out/Components/Layout/Scroller.d.ts +1 -0
  38. package/out/Components/Layout/Scroller.luau +1 -1
  39. package/out/Components/Layout/Tabs.d.ts +1 -1
  40. package/out/Components/Layout/Tabs.luau +37 -7
  41. package/out/Components/Layout/VStack.d.ts +4 -1
  42. package/out/Components/Layout/VStack.luau +2 -2
  43. package/out/Components/Layout/index.d.ts +1 -0
  44. package/out/Components/Layout/init.luau +3 -0
  45. package/out/Components/Navigation/Menu.d.ts +1 -1
  46. package/out/Components/Surface/Box.d.ts +5 -3
  47. package/out/Components/Surface/Box.luau +12 -3
  48. package/out/Components/Surface/Card.d.ts +8 -6
  49. package/out/Components/Surface/Card.luau +430 -26
  50. package/out/Components/Surface/Icon.d.ts +1 -1
  51. package/out/Components/Surface/Icon.luau +43 -4
  52. package/out/Components/Typography/Text.d.ts +1 -0
  53. package/out/Components/Typography/Text.luau +135 -13
  54. package/out/Contexts/row.context.d.ts +1 -1
  55. package/out/Contexts/theme.context.d.ts +2 -2
  56. package/out/Helpers/color.helper.d.ts +5 -3
  57. package/out/Helpers/color.helper.luau +62 -34
  58. package/out/Helpers/create-ui-story.d.ts +8 -6
  59. package/out/Helpers/create-ui-story.luau +48 -5
  60. package/out/Helpers/css.helper.d.ts +28 -2
  61. package/out/Helpers/css.helper.luau +208 -0
  62. package/out/Helpers/index.d.ts +1 -0
  63. package/out/Helpers/init.luau +3 -0
  64. package/out/Helpers/size.helper.d.ts +3 -1
  65. package/out/Helpers/size.helper.luau +10 -9
  66. package/out/Helpers/spacing.helper.d.ts +3 -3
  67. package/out/Helpers/typography.helper.d.ts +2 -2
  68. package/out/Interfaces/css.types.d.ts +28 -0
  69. package/out/Interfaces/css.types.luau +17 -0
  70. package/out/Interfaces/element.props.d.ts +61 -0
  71. package/out/Interfaces/element.props.luau +1 -0
  72. package/out/Interfaces/index.d.ts +4 -2
  73. package/out/Interfaces/init.luau +9 -3
  74. package/out/Interfaces/responsive.types.d.ts +26 -0
  75. package/out/Interfaces/semantics.d.ts +3 -0
  76. package/out/Interfaces/semantics.luau +2 -0
  77. package/out/Providers/app.provider.d.ts +2 -2
  78. package/out/Providers/theme.provider.d.ts +2 -2
  79. package/out/Theme/index.d.ts +1 -0
  80. package/out/Theme/theme.factory.d.ts +3 -3
  81. package/out/Theme/theme.style.d.ts +48 -0
  82. package/out/Theme/theme.style.luau +1 -0
  83. package/out/Theme/theme.template.d.ts +90 -36
  84. package/out/Theme/themes/dark.theme.d.ts +1 -1
  85. package/out/Theme/themes/dark.theme.luau +73 -1
  86. package/out/Theme/themes/default.theme.d.ts +2 -2
  87. package/out/Theme/themes/default.theme.luau +122 -12
  88. package/out/Theme/themes/index.d.ts +1 -0
  89. package/out/Theme/themes/init.luau +3 -0
  90. package/out/Theme/themes/sandstone.theme.d.ts +1 -1
  91. package/out/Theme/themes/sandstone.theme.luau +81 -10
  92. package/out/Theme/themes/wooden.theme.d.ts +1 -0
  93. package/out/Theme/themes/wooden.theme.luau +443 -0
  94. package/out/index.d.ts +8 -8
  95. package/package.json +20 -6
  96. package/out/Interfaces/clean.element.props.d.ts +0 -114
  97. /package/out/{Interfaces/userinput.d.ts → Helpers/input.helper.d.ts} +0 -0
  98. /package/out/{Interfaces/userinput.luau → Helpers/input.helper.luau} +0 -0
  99. /package/out/Interfaces/{clean.element.props.luau → responsive.types.luau} +0 -0
@@ -6,22 +6,144 @@ local Text = React.forwardRef(function(props, ref)
6
6
  local theme = React.useContext(CleanThemeContext)
7
7
  local style = props.typography or theme.typography[props.variant or "body"]
8
8
  local weight = if props.weight == "bold" then Enum.FontWeight.Bold else props.weight or style.weight or Enum.FontWeight.Regular
9
- return React.createElement("textlabel", {
9
+ local textwrapped = props.TextWrap ~= false and props.TextWrapped ~= false
10
+ local _condition = props.letterSpacing
11
+ if _condition == nil then
12
+ _condition = style.letterSpacing
13
+ end
14
+ local letterSpacing = _condition
15
+ -- Roblox text instances have no native letter-spacing property, so a nonzero
16
+ -- value is faked by splitting the text into one TextLabel per character laid
17
+ -- out in a UIListLayout row with the spacing as its Padding. This only makes
18
+ -- sense for short, single-line, plain text: RichText is forced off per-character
19
+ -- (markup tags can't survive being split apart), and wrapping/truncation are
20
+ -- moot since each character label auto-sizes to itself and never overflows.
21
+ if letterSpacing ~= nil and letterSpacing ~= 0 and props.text ~= "" then
22
+ local characters = {}
23
+ for index = 0, #props.text - 1 do
24
+ local _text = props.text
25
+ local _arg0 = index + 1
26
+ local _arg1 = index + 1
27
+ local _arg0_1 = string.sub(_text, _arg0, _arg1)
28
+ table.insert(characters, _arg0_1)
29
+ end
30
+ local _exp = React.createElement("uilistlayout", {
31
+ FillDirection = Enum.FillDirection.Horizontal,
32
+ SortOrder = Enum.SortOrder.LayoutOrder,
33
+ Padding = UDim.new(0, letterSpacing),
34
+ VerticalAlignment = Enum.VerticalAlignment.Center,
35
+ HorizontalAlignment = props.align or Enum.HorizontalAlignment.Left,
36
+ })
37
+ -- ▼ ReadonlyArray.map ▼
38
+ local _newValue = table.create(#characters)
39
+ local _callback = function(character, index)
40
+ local _attributes = {
41
+ key = index,
42
+ LayoutOrder = index,
43
+ Size = UDim2.fromScale(0, 0),
44
+ AutomaticSize = Enum.AutomaticSize.XY,
45
+ BackgroundTransparency = 1,
46
+ TextColor3 = props.TextColor3 or theme.colors.intents.primary.default.textColor,
47
+ Text = character,
48
+ }
49
+ local _condition_1 = props.LineHeight
50
+ if _condition_1 == nil then
51
+ _condition_1 = style.lineHeight
52
+ end
53
+ _attributes.LineHeight = _condition_1
54
+ _attributes.FontFace = Font.fromName(style.font.Name, weight)
55
+ _attributes.FontSize = style.size
56
+ _attributes.RichText = false
57
+ local _condition_2 = props.TextScaled
58
+ if _condition_2 == nil then
59
+ _condition_2 = false
60
+ end
61
+ _attributes.TextScaled = _condition_2
62
+ _attributes.TextStrokeColor3 = props.TextStrokeColor3
63
+ _attributes.TextStrokeTransparency = props.TextStrokeTransparency
64
+ _attributes.TextTransparency = props.TextTransparency
65
+ return React.createElement("textlabel", _attributes)
66
+ end
67
+ for _k, _v in characters do
68
+ _newValue[_k] = _callback(_v, _k - 1, characters)
69
+ end
70
+ -- ▲ ReadonlyArray.map ▲
71
+ return React.createElement("frame", {
72
+ Size = UDim2.fromScale(0, 0),
73
+ AutomaticSize = Enum.AutomaticSize.XY,
74
+ AnchorPoint = props.AnchorPoint,
75
+ BackgroundTransparency = 1,
76
+ Position = props.Position,
77
+ ZIndex = props.ZIndex,
78
+ LayoutOrder = props.LayoutOrder,
79
+ Visible = props.Visible,
80
+ Rotation = props.Rotation,
81
+ }, _exp, _newValue)
82
+ end
83
+ local _attributes = {
10
84
  ref = ref,
11
85
  Size = UDim2.fromScale(0, 0),
12
86
  AutomaticSize = Enum.AutomaticSize.XY,
13
- LineHeight = style.lineHeight,
14
- BackgroundTransparency = 1,
15
- TextXAlignment = props.align or (props.TextXAlignment or Enum.TextXAlignment.Left),
16
- TextColor3 = props.TextColor3 or theme.colors.intents.primary.default.textColor,
17
- Text = props.text,
18
- TextWrap = props.TextWrap == nil or props.TextWrap == true,
19
- FontFace = Font.fromName(style.font.Name, weight),
20
- FontSize = style.size,
21
- RichText = true,
22
- Event = props.Event,
23
- TextScaled = false,
24
- }, props.children)
87
+ AnchorPoint = props.AnchorPoint,
88
+ }
89
+ local _condition_1 = props.LineHeight
90
+ if _condition_1 == nil then
91
+ _condition_1 = style.lineHeight
92
+ end
93
+ _attributes.LineHeight = _condition_1
94
+ local _condition_2 = props.BackgroundTransparency
95
+ if _condition_2 == nil then
96
+ _condition_2 = 1
97
+ end
98
+ _attributes.BackgroundTransparency = _condition_2
99
+ _attributes.TextXAlignment = props.align or (props.TextXAlignment or Enum.TextXAlignment.Left)
100
+ _attributes.TextColor3 = props.TextColor3 or theme.colors.intents.primary.default.textColor
101
+ _attributes.Text = props.text
102
+ _attributes.Position = props.Position
103
+ _attributes.TextWrap = textwrapped
104
+ _attributes.TextWrapped = textwrapped
105
+ _attributes.FontFace = Font.fromName(style.font.Name, weight)
106
+ _attributes.FontSize = style.size
107
+ local _condition_3 = props.RichText
108
+ if _condition_3 == nil then
109
+ _condition_3 = true
110
+ end
111
+ _attributes.RichText = _condition_3
112
+ local _condition_4 = props.TextScaled
113
+ if _condition_4 == nil then
114
+ _condition_4 = false
115
+ end
116
+ _attributes.TextScaled = _condition_4
117
+ _attributes.ZIndex = props.ZIndex
118
+ _attributes.LayoutOrder = props.LayoutOrder
119
+ _attributes.Visible = props.Visible
120
+ _attributes.Rotation = props.Rotation
121
+ _attributes.Active = props.Active
122
+ _attributes.Archivable = props.Archivable
123
+ _attributes.BackgroundColor3 = props.BackgroundColor3
124
+ _attributes.BorderColor3 = props.BorderColor3
125
+ _attributes.BorderMode = props.BorderMode
126
+ _attributes.BorderSizePixel = props.BorderSizePixel
127
+ _attributes.ClipsDescendants = props.ClipsDescendants
128
+ _attributes.Selectable = props.Selectable
129
+ _attributes.SelectionImageObject = props.SelectionImageObject
130
+ _attributes.SizeConstraint = props.SizeConstraint
131
+ _attributes.Tag = props.Tag
132
+ _attributes.AutoLocalize = props.AutoLocalize
133
+ _attributes.RootLocalizationTable = props.RootLocalizationTable
134
+ _attributes.NextSelectionDown = props.NextSelectionDown
135
+ _attributes.NextSelectionLeft = props.NextSelectionLeft
136
+ _attributes.NextSelectionRight = props.NextSelectionRight
137
+ _attributes.NextSelectionUp = props.NextSelectionUp
138
+ _attributes.SelectionGroup = props.SelectionGroup
139
+ _attributes.SelectionOrder = props.SelectionOrder
140
+ _attributes.TextStrokeColor3 = props.TextStrokeColor3
141
+ _attributes.TextStrokeTransparency = props.TextStrokeTransparency
142
+ _attributes.TextTransparency = props.TextTransparency
143
+ _attributes.TextTruncate = props.TextTruncate
144
+ _attributes.Change = props.Change
145
+ _attributes.Event = props.Event
146
+ return React.createElement("textlabel", _attributes, props.children)
25
147
  end)
26
148
  return {
27
149
  Text = Text,
@@ -1,5 +1,5 @@
1
1
  import React from "@rbxts/react";
2
- import { Breakpoint } from "../Interfaces/clean.element.props";
2
+ import { Breakpoint } from "../Interfaces/responsive.types";
3
3
  export interface RowContextValue {
4
4
  width: number;
5
5
  breakpoint: Breakpoint;
@@ -1,3 +1,3 @@
1
1
  import React from "@rbxts/react";
2
- import { CleanTheme } from "../Theme/theme.template";
3
- export declare const CleanThemeContext: React.Context<CleanTheme>;
2
+ import { ThemeTemplate } from "../Theme/theme.template";
3
+ export declare const CleanThemeContext: React.Context<ThemeTemplate>;
@@ -1,9 +1,11 @@
1
- import { CleanTheme, InlineIntentColors, IntentScheme } from "../Theme";
1
+ import { ThemeTemplate, InlineIntentColors, IntentScheme } from "../Theme";
2
2
  import { ButtonFlag, Intent } from "../Interfaces";
3
3
  type ComponentIntentColors = Partial<Record<Intent, InlineIntentColors>> | Partial<Record<Intent, Partial<IntentScheme>>>;
4
4
  export declare class ColorHelper {
5
- static getIntentColors(theme: CleanTheme, intent: Intent | undefined, state?: ButtonFlag, componentColors?: ComponentIntentColors): IntentScheme;
6
- private static resolveComponentColors;
5
+ static getIntentColors(theme: ThemeTemplate, intent: Intent | undefined, state?: ButtonFlag, componentColors?: ComponentIntentColors, overrideColors?: ComponentIntentColors): IntentScheme;
6
+ private static mergeLayers;
7
+ private static resolveComponentDefaultLayer;
8
+ private static resolveComponentStateLayer;
7
9
  private static isInlineIntentColors;
8
10
  }
9
11
  export {};
@@ -13,7 +13,7 @@ do
13
13
  end
14
14
  function ColorHelper:constructor()
15
15
  end
16
- function ColorHelper:getIntentColors(theme, intent, state, componentColors)
16
+ function ColorHelper:getIntentColors(theme, intent, state, componentColors, overrideColors)
17
17
  if state == nil then
18
18
  state = "default"
19
19
  end
@@ -30,49 +30,77 @@ do
30
30
  _componentMatching = _componentMatching[selectedIntent]
31
31
  end
32
32
  local componentMatching = _componentMatching
33
- local _object = table.clone(defaultPrimary.default)
34
- setmetatable(_object, nil)
35
- local _condition = defaultPrimary[state]
36
- if _condition == nil then
37
- _condition = {}
33
+ local _overridePrimary = overrideColors
34
+ if _overridePrimary ~= nil then
35
+ _overridePrimary = _overridePrimary.primary
38
36
  end
39
- for _k, _v in _condition do
40
- _object[_k] = _v
37
+ local overridePrimary = _overridePrimary
38
+ local _overrideMatching = overrideColors
39
+ if _overrideMatching ~= nil then
40
+ _overrideMatching = _overrideMatching[selectedIntent]
41
41
  end
42
- for _k, _v in defaultMatching.default do
43
- _object[_k] = _v
44
- end
45
- local _condition_1 = defaultMatching[state]
46
- if _condition_1 == nil then
47
- _condition_1 = {}
48
- end
49
- for _k, _v in _condition_1 do
50
- _object[_k] = _v
51
- end
52
- for _k, _v in self:resolveComponentColors(componentPrimary, state) do
53
- _object[_k] = _v
54
- end
55
- for _k, _v in self:resolveComponentColors(componentMatching, state) do
56
- _object[_k] = _v
42
+ local overrideMatching = _overrideMatching
43
+ local layers = { defaultPrimary.default, defaultMatching.default, defaultPrimary[state], defaultMatching[state], self:resolveComponentDefaultLayer(componentPrimary), self:resolveComponentDefaultLayer(componentMatching), self:resolveComponentStateLayer(componentPrimary, state), self:resolveComponentStateLayer(componentMatching, state), self:resolveComponentDefaultLayer(overridePrimary), self:resolveComponentDefaultLayer(overrideMatching), self:resolveComponentStateLayer(overridePrimary, state), self:resolveComponentStateLayer(overrideMatching, state) }
44
+ return self:mergeLayers(layers)
45
+ end
46
+ function ColorHelper:mergeLayers(layers)
47
+ local merged = {}
48
+ local backgroundImage
49
+ local typography
50
+ for _, layer in layers do
51
+ if layer == nil then
52
+ continue
53
+ end
54
+ local _object = table.clone(merged)
55
+ setmetatable(_object, nil)
56
+ for _k, _v in layer do
57
+ _object[_k] = _v
58
+ end
59
+ merged = _object
60
+ if layer.backgroundImage ~= nil then
61
+ local _object_1 = {}
62
+ if backgroundImage then
63
+ for _k, _v in backgroundImage do
64
+ _object_1[_k] = _v
65
+ end
66
+ end
67
+ for _k, _v in layer.backgroundImage do
68
+ _object_1[_k] = _v
69
+ end
70
+ backgroundImage = _object_1
71
+ end
72
+ if layer.typography ~= nil then
73
+ local _object_1 = {}
74
+ if typography then
75
+ for _k, _v in typography do
76
+ _object_1[_k] = _v
77
+ end
78
+ end
79
+ for _k, _v in layer.typography do
80
+ _object_1[_k] = _v
81
+ end
82
+ typography = _object_1
83
+ end
57
84
  end
58
- return _object
85
+ merged.backgroundImage = backgroundImage
86
+ merged.typography = typography
87
+ return merged
59
88
  end
60
- function ColorHelper:resolveComponentColors(colors, state)
89
+ function ColorHelper:resolveComponentDefaultLayer(colors)
61
90
  if colors == nil then
62
- return {}
91
+ return nil
63
92
  end
64
93
  if self:isInlineIntentColors(colors) then
65
- local _object = table.clone((colors.default or {}))
66
- setmetatable(_object, nil)
67
- for _k, _v in (colors[state] or {}) do
68
- _object[_k] = _v
69
- end
70
- return _object
94
+ return colors.default
71
95
  end
72
- -- A direct Partial<IntentScheme> has no state variants,
73
- -- so the requested state is ignored.
74
96
  return colors
75
97
  end
98
+ function ColorHelper:resolveComponentStateLayer(colors, state)
99
+ if colors == nil or not self:isInlineIntentColors(colors) then
100
+ return nil
101
+ end
102
+ return colors[state]
103
+ end
76
104
  function ColorHelper:isInlineIntentColors(colors)
77
105
  local statefulColors = colors
78
106
  return statefulColors.default ~= nil or statefulColors.hover ~= nil or statefulColors.focus ~= nil
@@ -2,15 +2,17 @@ import React from "@rbxts/react";
2
2
  import ReactRoblox from "@rbxts/react-roblox";
3
3
  import { InferProps } from "@rbxts/ui-labs";
4
4
  declare const controls: {
5
- Theme: import("@rbxts/ui-labs/src/ControlTypings/Advanced").AdvancedTypes.Choose<"Default" | "Dark" | "Sandstone">;
5
+ Theme: import("@rbxts/ui-labs/src/ControlTypings/Advanced").AdvancedTypes.Choose<"Default" | "Dark" | "Sandstone" | "Wooden">;
6
6
  };
7
- type StoryProps = InferProps<typeof controls>;
8
- export declare function createStory(StoryComponent: (props: StoryProps) => React.ReactNode): {
7
+ type StoryControl = Parameters<typeof import("@rbxts/ui-labs").Ordered>[0];
8
+ type StoryControls = Record<string, StoryControl>;
9
+ type StoryProps<T extends StoryControls> = InferProps<typeof controls & T>;
10
+ export declare function createStory<T extends StoryControls = {}>(StoryComponent: (props: StoryProps<T>) => React.ReactNode, additionalControls?: T): {
9
11
  react: typeof React;
10
12
  reactRoblox: typeof ReactRoblox;
11
13
  controls: {
12
- Theme: import("@rbxts/ui-labs/src/ControlTypings/Advanced").AdvancedTypes.Choose<"Default" | "Dark" | "Sandstone">;
13
- };
14
- story: (props: StoryProps) => React.JSX.Element;
14
+ Theme: import("@rbxts/ui-labs/src/ControlTypings/Advanced").AdvancedTypes.Choose<"Default" | "Dark" | "Sandstone" | "Wooden">;
15
+ } & T;
16
+ story: (props: StoryProps<T>) => React.JSX.Element;
15
17
  };
16
18
  export {};
@@ -6,24 +6,67 @@ local _Theme = TS.import(script, script.Parent.Parent, "Theme")
6
6
  local DarkTheme = _Theme.DarkTheme
7
7
  local DefaultTheme = _Theme.DefaultTheme
8
8
  local SandstoneTheme = _Theme.SandstoneTheme
9
+ local WoodenTheme = _Theme.WoodenTheme
9
10
  local Choose = TS.import(script, TS.getModule(script, "@rbxts", "ui-labs").src).Choose
10
11
  local CleanUiProvider = TS.import(script, script.Parent.Parent, "Providers", "app.provider").CleanUiProvider
12
+ local THEME_ATTRIBUTE = "UILabsSelectedTheme"
13
+ local themeControl = Choose({ "Default", "Dark", "Sandstone", "Wooden" })
14
+ local persistedTheme = script:GetAttribute(THEME_ATTRIBUTE)
15
+ local function isThemeName(value)
16
+ local _value = value
17
+ local _condition = type(_value) == "string"
18
+ if _condition then
19
+ local _exp = themeControl.List
20
+ -- ▼ ReadonlyArray.some ▼
21
+ local _result = false
22
+ local _callback = function(theme)
23
+ return theme == value
24
+ end
25
+ for _k, _v in _exp do
26
+ if _callback(_v, _k - 1, _exp) then
27
+ _result = true
28
+ break
29
+ end
30
+ end
31
+ -- ▲ ReadonlyArray.some ▲
32
+ _condition = _result
33
+ end
34
+ return _condition
35
+ end
36
+ if isThemeName(persistedTheme) then
37
+ themeControl.ControlValue = persistedTheme
38
+ end
11
39
  local controls = {
12
- Theme = Choose({ "Default", "Dark", "Sandstone" }),
40
+ Theme = themeControl,
13
41
  }
14
- local function createStory(StoryComponent)
42
+ local function createStory(StoryComponent, additionalControls)
43
+ local _object = {}
44
+ if additionalControls then
45
+ for _k, _v in additionalControls do
46
+ _object[_k] = _v
47
+ end
48
+ end
49
+ for _k, _v in controls do
50
+ _object[_k] = _v
51
+ end
52
+ local storyControls = _object
15
53
  return {
16
54
  react = React,
17
55
  reactRoblox = ReactRoblox,
18
- controls = controls,
56
+ controls = storyControls,
19
57
  story = function(props)
58
+ local baseProps = props
59
+ script:SetAttribute(THEME_ATTRIBUTE, baseProps.controls.Theme)
20
60
  local theme = DefaultTheme
21
- if props.controls.Theme == "Dark" then
61
+ if baseProps.controls.Theme == "Dark" then
22
62
  theme = DarkTheme
23
63
  end
24
- if props.controls.Theme == "Sandstone" then
64
+ if baseProps.controls.Theme == "Sandstone" then
25
65
  theme = SandstoneTheme
26
66
  end
67
+ if baseProps.controls.Theme == "Wooden" then
68
+ theme = WoodenTheme
69
+ end
27
70
  local _attributes = table.clone(props)
28
71
  setmetatable(_attributes, nil)
29
72
  return React.createElement(CleanUiProvider, {
@@ -1,13 +1,39 @@
1
- import { CssBoxShadow, CssShadow, CssSize } from "../Interfaces/clean.element.props";
1
+ import { CssBoxShadow, CssShadow, CssCalcSize, CssQuad, CssDual, CssSliceInset } from "../Interfaces/css.types";
2
+ import { CssBackgroundImage } from "../Theme";
2
3
  interface ParsedShadow {
3
4
  offset: UDim2;
4
5
  blurRadius: UDim;
5
6
  spread: UDim2;
6
7
  }
8
+ interface ParsedQuad {
9
+ top: number;
10
+ right: number;
11
+ bottom: number;
12
+ left: number;
13
+ }
14
+ interface ParsedSliceInset {
15
+ x1: number;
16
+ y1: number;
17
+ x2: number;
18
+ y2: number;
19
+ }
7
20
  export declare class CssHelper {
8
21
  static parseCssShadow(value: CssShadow): ParsedShadow | undefined;
9
22
  private static isZero;
10
- static parseCssSize(value: CssSize): UDim;
23
+ static parseCssSize(value: CssCalcSize): UDim;
24
+ static parseCssQuad(value: CssQuad): ParsedQuad;
25
+ private static toRawPixels;
26
+ static parseCssSliceInset(value: CssSliceInset): ParsedSliceInset;
27
+ static parseCssDual(value: CssDual): UDim2;
11
28
  static ResolveShadow(shadow: CssBoxShadow): React.InstanceProps<UIShadow>;
29
+ static resolveBackgroundImage(value: Partial<CssBackgroundImage> | undefined): {
30
+ Image?: string;
31
+ ImageColor3?: Color3;
32
+ ImageTransparency?: number;
33
+ ScaleType?: CssBackgroundImage["size"];
34
+ SliceCenter?: Rect;
35
+ SliceScale?: number;
36
+ TileSize?: UDim2;
37
+ };
12
38
  }
13
39
  export {};
@@ -86,6 +86,24 @@ do
86
86
  if type(_value) == "number" then
87
87
  return UDim.new(0, value)
88
88
  end
89
+ -- The one CSS calc() shape supported: "<percent>% - <px>px" /
90
+ -- "<percent>% + <px>px" (e.g. "100% - 50px") maps directly onto
91
+ -- UDim(scale, offset) — split on the literal " - "/" + " separator
92
+ -- and parse each term with this same function. Anything without
93
+ -- either separator falls through to the single-token parsing below,
94
+ -- unchanged.
95
+ local minusParts = string.split(value, " - ")
96
+ if #minusParts == 2 then
97
+ local scale = self:parseCssSize(minusParts[1]).Scale
98
+ local offset = self:parseCssSize(minusParts[2]).Offset
99
+ return UDim.new(scale, -offset)
100
+ end
101
+ local plusParts = string.split(value, " + ")
102
+ if #plusParts == 2 then
103
+ local scale = self:parseCssSize(plusParts[1]).Scale
104
+ local offset = self:parseCssSize(plusParts[2]).Offset
105
+ return UDim.new(scale, offset)
106
+ end
89
107
  if string.sub(value, -1) == "%" then
90
108
  local _condition = tonumber(string.sub(value, 1, -2))
91
109
  if _condition == nil then
@@ -108,6 +126,179 @@ do
108
126
  end
109
127
  return UDim.new(0, _condition)
110
128
  end
129
+ function CssHelper:parseCssQuad(value)
130
+ local _value = value
131
+ if type(_value) == "number" then
132
+ local size = self:parseCssSize(value).Offset
133
+ return {
134
+ top = size,
135
+ right = size,
136
+ bottom = size,
137
+ left = size,
138
+ }
139
+ end
140
+ local _exp = string.split(value, " ")
141
+ -- ▼ ReadonlyArray.filter ▼
142
+ local _newValue = {}
143
+ local _callback = function(part)
144
+ return #part > 0
145
+ end
146
+ local _length = 0
147
+ for _k, _v in _exp do
148
+ if _callback(_v, _k - 1, _exp) == true then
149
+ _length += 1
150
+ _newValue[_length] = _v
151
+ end
152
+ end
153
+ -- ▲ ReadonlyArray.filter ▲
154
+ local parts = _newValue
155
+ local _self = self
156
+ local _condition = parts[1]
157
+ if _condition == nil then
158
+ _condition = "0"
159
+ end
160
+ local top = _self:parseCssSize(_condition).Offset
161
+ local _self_1 = self
162
+ local _condition_1 = parts[2]
163
+ if _condition_1 == nil then
164
+ _condition_1 = parts[1]
165
+ if _condition_1 == nil then
166
+ _condition_1 = "0"
167
+ end
168
+ end
169
+ local right = _self_1:parseCssSize(_condition_1).Offset
170
+ local _self_2 = self
171
+ local _condition_2 = parts[3]
172
+ if _condition_2 == nil then
173
+ _condition_2 = parts[1]
174
+ if _condition_2 == nil then
175
+ _condition_2 = "0"
176
+ end
177
+ end
178
+ local bottom = _self_2:parseCssSize(_condition_2).Offset
179
+ local _self_3 = self
180
+ local _condition_3 = parts[4]
181
+ if _condition_3 == nil then
182
+ _condition_3 = parts[2]
183
+ if _condition_3 == nil then
184
+ _condition_3 = parts[1]
185
+ if _condition_3 == nil then
186
+ _condition_3 = "0"
187
+ end
188
+ end
189
+ end
190
+ local left = _self_3:parseCssSize(_condition_3).Offset
191
+ return {
192
+ top = top,
193
+ right = right,
194
+ bottom = bottom,
195
+ left = left,
196
+ }
197
+ end
198
+ function CssHelper:toRawPixels(value)
199
+ local _value = value
200
+ if type(_value) == "number" then
201
+ return value
202
+ end
203
+ if string.sub(value, -1) == "%" then
204
+ local _condition = tonumber(string.sub(value, 1, -2))
205
+ if _condition == nil then
206
+ _condition = 0
207
+ end
208
+ return _condition
209
+ end
210
+ if string.sub(value, -2) == "px" then
211
+ local _condition = tonumber(string.sub(value, 1, -3))
212
+ if _condition == nil then
213
+ _condition = 0
214
+ end
215
+ return _condition
216
+ end
217
+ local _condition = tonumber(value)
218
+ if _condition == nil then
219
+ _condition = 0
220
+ end
221
+ return _condition
222
+ end
223
+ function CssHelper:parseCssSliceInset(value)
224
+ local _exp = string.split(value, " ")
225
+ -- ▼ ReadonlyArray.filter ▼
226
+ local _newValue = {}
227
+ local _callback = function(part)
228
+ return #part > 0
229
+ end
230
+ local _length = 0
231
+ for _k, _v in _exp do
232
+ if _callback(_v, _k - 1, _exp) == true then
233
+ _length += 1
234
+ _newValue[_length] = _v
235
+ end
236
+ end
237
+ -- ▲ ReadonlyArray.filter ▲
238
+ local parts = _newValue
239
+ -- ▼ ReadonlyArray.map ▼
240
+ local _newValue_1 = table.create(#parts)
241
+ local _callback_1 = function(part)
242
+ return self:toRawPixels(part)
243
+ end
244
+ for _k, _v in parts do
245
+ _newValue_1[_k] = _callback_1(_v, _k - 1, parts)
246
+ end
247
+ -- ▲ ReadonlyArray.map ▲
248
+ local pixels = _newValue_1
249
+ if #pixels == 2 then
250
+ return {
251
+ x1 = pixels[1],
252
+ y1 = pixels[1],
253
+ x2 = pixels[2],
254
+ y2 = pixels[2],
255
+ }
256
+ end
257
+ return {
258
+ x1 = pixels[1],
259
+ y1 = pixels[2],
260
+ x2 = pixels[3],
261
+ y2 = pixels[4],
262
+ }
263
+ end
264
+ function CssHelper:parseCssDual(value)
265
+ local _value = value
266
+ if type(_value) == "number" then
267
+ local size = self:parseCssSize(value)
268
+ return UDim2.new(size, size)
269
+ end
270
+ local _exp = string.split(value, " ")
271
+ -- ▼ ReadonlyArray.filter ▼
272
+ local _newValue = {}
273
+ local _callback = function(part)
274
+ return #part > 0
275
+ end
276
+ local _length = 0
277
+ for _k, _v in _exp do
278
+ if _callback(_v, _k - 1, _exp) == true then
279
+ _length += 1
280
+ _newValue[_length] = _v
281
+ end
282
+ end
283
+ -- ▲ ReadonlyArray.filter ▲
284
+ local parts = _newValue
285
+ local _self = self
286
+ local _condition = parts[1]
287
+ if _condition == nil then
288
+ _condition = "0"
289
+ end
290
+ local x = _self:parseCssSize(_condition)
291
+ local _self_1 = self
292
+ local _condition_1 = parts[2]
293
+ if _condition_1 == nil then
294
+ _condition_1 = parts[1]
295
+ if _condition_1 == nil then
296
+ _condition_1 = "0"
297
+ end
298
+ end
299
+ local y = _self_1:parseCssSize(_condition_1)
300
+ return UDim2.new(x, y)
301
+ end
111
302
  function CssHelper:ResolveShadow(shadow)
112
303
  local offset = self:parseCssShadow(shadow.shadow)
113
304
  local _object = {}
@@ -133,6 +324,23 @@ do
133
324
  _object.Transparency = shadow.transparency
134
325
  return _object
135
326
  end
327
+ function CssHelper:resolveBackgroundImage(value)
328
+ if value == nil then
329
+ return {}
330
+ end
331
+ local slice = if value.slice ~= nil then self:parseCssSliceInset(value.slice) else nil
332
+ local _object = {}
333
+ local _left = "Image"
334
+ local _image = value.image
335
+ _object[_left] = if type(_image) == "number" then `rbxassetid://{value.image}` else value.image
336
+ _object.ImageColor3 = value.tintColor
337
+ _object.ImageTransparency = value.transparency
338
+ _object.ScaleType = if slice ~= nil then Enum.ScaleType.Slice else (value.size or Enum.ScaleType.Stretch)
339
+ _object.SliceCenter = if slice ~= nil then Rect.new(slice.x1, slice.y1, slice.x2, slice.y2) else nil
340
+ _object.SliceScale = value.sliceScale
341
+ _object.TileSize = if value.tileSize ~= nil then self:parseCssDual(value.tileSize) else nil
342
+ return _object
343
+ end
136
344
  end
137
345
  return {
138
346
  CssHelper = CssHelper,
@@ -2,6 +2,7 @@ export * from './breakpoint.helper';
2
2
  export * from './color.helper';
3
3
  export * from './css.helper';
4
4
  export * from './gui.helper';
5
+ export * from './input.helper';
5
6
  export * from './size.helper';
6
7
  export * from './spacing.helper';
7
8
  export * from './typography.helper';