@rbxts/react-clean-ui 1.2.9 → 1.4.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.
Files changed (37) hide show
  1. package/LICENSE +15 -0
  2. package/README.md +111 -1
  3. package/out/Components/Chart/Pie.luau +13 -20
  4. package/out/Components/Input/Button.d.ts +3 -1
  5. package/out/Components/Input/Button.luau +4 -0
  6. package/out/Components/Interaction/Tooltip.d.ts +2 -0
  7. package/out/Components/Interaction/Tooltip.luau +62 -34
  8. package/out/Components/Layout/Accordion.d.ts +14 -3
  9. package/out/Components/Layout/Accordion.luau +76 -10
  10. package/out/Components/Layout/Draggable.d.ts +7 -4
  11. package/out/Components/Layout/Draggable.luau +191 -98
  12. package/out/Components/Layout/Droppable.d.ts +5 -2
  13. package/out/Components/Layout/Droppable.luau +50 -10
  14. package/out/Components/Layout/FadeGroup.d.ts +6 -0
  15. package/out/Components/Layout/FadeGroup.luau +58 -0
  16. package/out/Components/Layout/Group.d.ts +2 -2
  17. package/out/Components/Layout/Tabs.d.ts +1 -0
  18. package/out/Components/Layout/Tabs.luau +1 -0
  19. package/out/Components/Layout/index.d.ts +1 -0
  20. package/out/Components/Layout/init.luau +3 -0
  21. package/out/Components/Surface/Card.d.ts +1 -3
  22. package/out/Components/Surface/Icon.luau +1 -0
  23. package/out/Components/Typography/Text.luau +2 -2
  24. package/out/Contexts/draggable.context.d.ts +11 -0
  25. package/out/Contexts/draggable.context.luau +5 -0
  26. package/out/Helpers/create-ui-story.d.ts +1 -1
  27. package/out/Helpers/element.helper.d.ts +8 -0
  28. package/out/Helpers/element.helper.luau +77 -0
  29. package/out/Helpers/gui.helper.d.ts +6 -0
  30. package/out/Helpers/gui.helper.luau +141 -7
  31. package/out/Helpers/index.d.ts +1 -0
  32. package/out/Helpers/init.luau +3 -0
  33. package/out/Helpers/size.helper.luau +2 -10
  34. package/out/Providers/registry.provider.d.ts +7 -3
  35. package/out/Providers/registry.provider.luau +15 -15
  36. package/out/Theme/themes/wooden.theme.luau +9 -0
  37. package/package.json +1 -1
@@ -30,6 +30,7 @@ local function SpinningIcon(props)
30
30
  _attributes.BorderSizePixel = 0
31
31
  _attributes.Size = UDim2.fromOffset(0, 0)
32
32
  _attributes.AutomaticSize = Enum.AutomaticSize.XY
33
+ _attributes.LayoutOrder = props.LayoutOrder
33
34
  return React.createElement("frame", _attributes, React.createElement(Icon, {
34
35
  Size = props.Size,
35
36
  color = props.color,
@@ -89,8 +89,8 @@ local Text = React.forwardRef(function(props, ref)
89
89
  end
90
90
  _attributes.key = _condition_1
91
91
  _attributes.ref = ref
92
- _attributes.Size = UDim2.fromScale(0, 0)
93
- _attributes.AutomaticSize = Enum.AutomaticSize.XY
92
+ _attributes.Size = props.Size or UDim2.fromScale(0, 0)
93
+ _attributes.AutomaticSize = props.AutomaticSize or Enum.AutomaticSize.XY
94
94
  _attributes.AnchorPoint = props.AnchorPoint
95
95
  local _condition_2 = props.LineHeight
96
96
  if _condition_2 == nil then
@@ -1,4 +1,10 @@
1
1
  import React from "@rbxts/react";
2
+ export interface DragEventInfo {
3
+ inputType: Enum.UserInputType;
4
+ input: InputObject;
5
+ position: Vector2;
6
+ id?: string;
7
+ }
2
8
  export interface DraggableContextValue {
3
9
  isDragging: boolean;
4
10
  beginDrag: (input: InputObject, handle: GuiObject) => void;
@@ -6,3 +12,8 @@ export interface DraggableContextValue {
6
12
  endDrag: (input: InputObject) => void;
7
13
  }
8
14
  export declare const DraggableContext: React.Context<DraggableContextValue | undefined>;
15
+ export interface DragStateContextValue {
16
+ preview: boolean;
17
+ dragging: boolean;
18
+ }
19
+ export declare const DragStateContext: React.Context<DragStateContextValue>;
@@ -2,6 +2,11 @@
2
2
  local TS = _G[script]
3
3
  local React = TS.import(script, TS.getModule(script, "@rbxts", "react"))
4
4
  local DraggableContext = React.createContext(nil)
5
+ local DragStateContext = React.createContext({
6
+ preview = false,
7
+ dragging = false,
8
+ })
5
9
  return {
6
10
  DraggableContext = DraggableContext,
11
+ DragStateContext = DragStateContext,
7
12
  }
@@ -7,7 +7,7 @@ declare const controls: {
7
7
  type StoryControl = Parameters<typeof import("@rbxts/ui-labs").Ordered>[0];
8
8
  type StoryControls = Record<string, StoryControl>;
9
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): {
10
+ export declare function createStory<T extends StoryControls = Record<never, never>>(StoryComponent: (props: StoryProps<T>) => React.ReactNode, additionalControls?: T): {
11
11
  react: typeof React;
12
12
  reactRoblox: typeof ReactRoblox;
13
13
  controls: {
@@ -0,0 +1,8 @@
1
+ import React from "@rbxts/react";
2
+ type EventCallback = (...args: never[]) => void;
3
+ export declare class ElementHelper {
4
+ static isHostElement(element: React.ReactElement): boolean;
5
+ static getEventKey(name: string): unknown;
6
+ static cloneWithEvents<P>(element: React.ReactElement<P>, props: Record<string, unknown>, events: Record<string, EventCallback>): React.ReactElement<P>;
7
+ }
8
+ export {};
@@ -0,0 +1,77 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local React = TS.import(script, TS.getModule(script, "@rbxts", "react"))
4
+ local ElementHelper
5
+ do
6
+ ElementHelper = setmetatable({}, {
7
+ __tostring = function()
8
+ return "ElementHelper"
9
+ end,
10
+ })
11
+ ElementHelper.__index = ElementHelper
12
+ function ElementHelper.new(...)
13
+ local self = setmetatable({}, ElementHelper)
14
+ return self:constructor(...) or self
15
+ end
16
+ function ElementHelper:constructor()
17
+ end
18
+ function ElementHelper:isHostElement(element)
19
+ local _type = element.type
20
+ return type(_type) == "string"
21
+ end
22
+ function ElementHelper:getEventKey(name)
23
+ return React.Event[name]
24
+ end
25
+ function ElementHelper:cloneWithEvents(element, props, events)
26
+ local config = {}
27
+ for key, value in pairs(props) do
28
+ config[key] = value
29
+ end
30
+ local elementProps = element.props
31
+ if self:isHostElement(element) then
32
+ for name, handler in pairs(events) do
33
+ local key = self:getEventKey(name)
34
+ local original = elementProps[key]
35
+ config[key] = function(...)
36
+ local args = { ... }
37
+ local _result = original
38
+ if _result ~= nil then
39
+ _result(unpack(args))
40
+ end
41
+ handler(unpack(args))
42
+ end
43
+ end
44
+ else
45
+ local originalEvents = elementProps.Event
46
+ local _result
47
+ if originalEvents ~= nil then
48
+ local _object = table.clone(originalEvents)
49
+ setmetatable(_object, nil)
50
+ _result = _object
51
+ else
52
+ _result = {}
53
+ end
54
+ local mergedEvents = _result
55
+ for name, handler in pairs(events) do
56
+ local _original = originalEvents
57
+ if _original ~= nil then
58
+ _original = _original[name]
59
+ end
60
+ local original = _original
61
+ mergedEvents[name] = function(...)
62
+ local args = { ... }
63
+ local _result_1 = original
64
+ if _result_1 ~= nil then
65
+ _result_1(unpack(args))
66
+ end
67
+ handler(unpack(args))
68
+ end
69
+ end
70
+ config.Event = mergedEvents
71
+ end
72
+ return React.cloneElement(element, config)
73
+ end
74
+ end
75
+ return {
76
+ ElementHelper = ElementHelper,
77
+ }
@@ -5,6 +5,12 @@ export declare class GuiHelper {
5
5
  static getGuiObjectsAtPosition(instance: Instance, point: Vector2): GuiObject[];
6
6
  static getGuiRenderOrder(instance: Instance): GuiObject[];
7
7
  private static getGuiRoot;
8
+ static getRenderSurface(instance: Instance): LayerCollector | undefined;
9
+ static isGuiObjectHitAtPoint(guiObject: GuiObject, point: Vector2): boolean;
10
+ static isRenderedAbove(a: GuiObject, b: GuiObject): boolean;
11
+ private static isLaterInTree;
12
+ private static getDivergingAncestors;
13
+ private static getChildIndex;
8
14
  private static getRenderSurfaces;
9
15
  private static appendGuiObjects;
10
16
  }
@@ -64,20 +64,152 @@ do
64
64
  return result
65
65
  end
66
66
  function GuiHelper:getGuiRoot(instance)
67
- if RunService:IsRunning() then
67
+ local surface = self:findHighestAncestorOfClass(instance, "LayerCollector")
68
+ local _result = surface
69
+ if _result ~= nil then
70
+ _result = _result.Parent
71
+ end
72
+ if _result ~= nil then
73
+ return surface.Parent
74
+ end
75
+ if RunService:IsRunning() and Players.LocalPlayer ~= nil then
68
76
  return Players.LocalPlayer:WaitForChild("PlayerGui")
69
77
  end
70
- local r = self:findHighestAncestorOfClass(instance, "PluginGuiService")
71
- if r == nil then
72
- error(`No root`)
78
+ local root = instance
79
+ while root.Parent ~= nil and root.Parent ~= game do
80
+ root = root.Parent
81
+ end
82
+ return root
83
+ end
84
+ function GuiHelper:getRenderSurface(instance)
85
+ return instance:FindFirstAncestorWhichIsA("LayerCollector")
86
+ end
87
+ function GuiHelper:isGuiObjectHitAtPoint(guiObject, point)
88
+ if not guiObject.Visible or not self:isPointInsideGuiObject(guiObject, point) then
89
+ return false
90
+ end
91
+ local current = guiObject.Parent
92
+ while current ~= nil do
93
+ if current:IsA("LayerCollector") then
94
+ return current.Enabled and not current:IsA("SurfaceGuiBase")
95
+ end
96
+ if current:IsA("GuiObject") then
97
+ if not current.Visible then
98
+ return false
99
+ end
100
+ if (current.ClipsDescendants or current:IsA("CanvasGroup")) and not self:isPointInsideGuiObject(current, point) then
101
+ return false
102
+ end
103
+ end
104
+ current = current.Parent
105
+ end
106
+ return false
107
+ end
108
+ function GuiHelper:isRenderedAbove(a, b)
109
+ if a == b then
110
+ return false
111
+ end
112
+ local surfaceA = self:getRenderSurface(a)
113
+ local surfaceB = self:getRenderSurface(b)
114
+ if surfaceA ~= surfaceB then
115
+ local _result = surfaceA
116
+ if _result ~= nil then
117
+ _result = _result:IsA("ScreenGui")
118
+ end
119
+ local orderA = if _result then surfaceA.DisplayOrder else 0
120
+ local _result_1 = surfaceB
121
+ if _result_1 ~= nil then
122
+ _result_1 = _result_1:IsA("ScreenGui")
123
+ end
124
+ local orderB = if _result_1 then surfaceB.DisplayOrder else 0
125
+ if orderA ~= orderB then
126
+ return orderA > orderB
127
+ end
128
+ return self:isLaterInTree(surfaceA or a, surfaceB or b)
129
+ end
130
+ local _result = surfaceA
131
+ if _result ~= nil then
132
+ _result = _result.ZIndexBehavior
133
+ end
134
+ local _condition = _result == Enum.ZIndexBehavior.Global
135
+ if _condition then
136
+ _condition = a.ZIndex ~= b.ZIndex
137
+ end
138
+ if _condition then
139
+ return a.ZIndex > b.ZIndex
140
+ end
141
+ if a:IsDescendantOf(b) then
142
+ return true
143
+ end
144
+ if b:IsDescendantOf(a) then
145
+ return false
146
+ end
147
+ local _result_1 = surfaceA
148
+ if _result_1 ~= nil then
149
+ _result_1 = _result_1.ZIndexBehavior
150
+ end
151
+ if _result_1 == Enum.ZIndexBehavior.Global then
152
+ return self:isLaterInTree(a, b)
153
+ end
154
+ local divergence = self:getDivergingAncestors(a, b)
155
+ if divergence == nil then
156
+ return false
157
+ end
158
+ local _binding = divergence
159
+ local branchA = _binding[1]
160
+ local branchB = _binding[2]
161
+ if branchA:IsA("GuiObject") and branchB:IsA("GuiObject") and branchA.ZIndex ~= branchB.ZIndex then
162
+ return branchA.ZIndex > branchB.ZIndex
163
+ end
164
+ return self:getChildIndex(branchA) > self:getChildIndex(branchB)
165
+ end
166
+ function GuiHelper:isLaterInTree(a, b)
167
+ local divergence = self:getDivergingAncestors(a, b)
168
+ if divergence == nil then
169
+ return false
170
+ end
171
+ return self:getChildIndex(divergence[1]) > self:getChildIndex(divergence[2])
172
+ end
173
+ function GuiHelper:getDivergingAncestors(a, b)
174
+ local branchByAncestor = {}
175
+ local previous = a
176
+ local current = a.Parent
177
+ while current ~= nil do
178
+ local _current = current
179
+ local _previous = previous
180
+ branchByAncestor[_current] = _previous
181
+ previous = current
182
+ current = current.Parent
183
+ end
184
+ previous = b
185
+ current = b.Parent
186
+ while current ~= nil do
187
+ local _current = current
188
+ local branchA = branchByAncestor[_current]
189
+ if branchA ~= nil then
190
+ return { branchA, previous }
191
+ end
192
+ previous = current
193
+ current = current.Parent
194
+ end
195
+ return nil
196
+ end
197
+ function GuiHelper:getChildIndex(instance)
198
+ local parent = instance.Parent
199
+ if parent == nil then
200
+ return 0
73
201
  end
74
- return r
202
+ local _exp = parent:GetChildren()
203
+ local _instance = instance
204
+ return (table.find(_exp, _instance) or 0) - 1
75
205
  end
76
206
  function GuiHelper:getRenderSurfaces(root)
77
207
  local surfaces = {}
78
208
  local visit
79
209
  visit = function(instance)
80
- for index, child in ipairs(instance:GetChildren()) do
210
+ local instanceChildren = instance:GetChildren()
211
+ for index = 0, #instanceChildren - 1 do
212
+ local child = instanceChildren[index + 1]
81
213
  if child:IsA("LayerCollector") then
82
214
  local _arg0 = {
83
215
  root = child,
@@ -102,7 +234,9 @@ do
102
234
  end
103
235
  function GuiHelper:appendGuiObjects(parent, result)
104
236
  local children = {}
105
- for index, child in ipairs(parent:GetChildren()) do
237
+ local parentChildren = parent:GetChildren()
238
+ for index = 0, #parentChildren - 1 do
239
+ local child = parentChildren[index + 1]
106
240
  if not child:IsA("GuiObject") then
107
241
  continue
108
242
  end
@@ -1,6 +1,7 @@
1
1
  export * from './breakpoint.helper';
2
2
  export * from './color.helper';
3
3
  export * from './css.helper';
4
+ export * from './element.helper';
4
5
  export * from './gui.helper';
5
6
  export * from './input.helper';
6
7
  export * from './size.helper';
@@ -10,6 +10,9 @@ end
10
10
  for _k, _v in TS.import(script, script, "css.helper") or {} do
11
11
  exports[_k] = _v
12
12
  end
13
+ for _k, _v in TS.import(script, script, "element.helper") or {} do
14
+ exports[_k] = _v
15
+ end
13
16
  for _k, _v in TS.import(script, script, "gui.helper") or {} do
14
17
  exports[_k] = _v
15
18
  end
@@ -65,21 +65,13 @@ do
65
65
  end
66
66
  local width = if props.width == "Auto" then nil else props.width
67
67
  local height = if props.height == "Auto" then nil else props.height
68
- local _condition = props.Size ~= nil
69
- if not _condition then
70
- local _condition_1 = width
71
- if _condition_1 ~= 0 and _condition_1 == _condition_1 and _condition_1 ~= "" and _condition_1 then
72
- _condition_1 = height
73
- end
74
- _condition = _condition_1
75
- end
76
- if _condition ~= 0 and _condition == _condition and _condition ~= "" and _condition then
68
+ if props.Size ~= nil or (width ~= nil and width ~= 0 and height ~= nil and height ~= 0) then
77
69
  return Enum.AutomaticSize.None
78
70
  end
79
71
  if width == nil and height == nil and defaultValue == nil then
80
72
  return Enum.AutomaticSize.XY
81
73
  end
82
- if not (width ~= 0 and width == width and width ~= "" and width) then
74
+ if width == nil or width == 0 then
83
75
  return Enum.AutomaticSize.X
84
76
  end
85
77
  return if defaultValue ~= nil then defaultValue else Enum.AutomaticSize.Y
@@ -1,12 +1,14 @@
1
1
  import React from "@rbxts/react";
2
- import { DraggableContextValue } from "../Contexts";
3
- export interface RegistryKey<T extends defined> {
2
+ import { DragEventInfo, DraggableContextValue } from "../Contexts";
3
+ export interface RegistryKey<_T extends defined> {
4
4
  readonly name: string;
5
5
  }
6
6
  export interface DroppableRegistration {
7
7
  guiObject: GuiObject;
8
8
  id?: string;
9
- drop: (draggedObject: GuiObject) => void;
9
+ drop: (draggedObject: GuiObject, info?: DragEventInfo) => void;
10
+ dragEnter?: (draggedObject: GuiObject, info: DragEventInfo) => void;
11
+ dragLeave?: (draggedObject: GuiObject, info: DragEventInfo) => void;
10
12
  }
11
13
  export declare const DroppableRegistryKey: RegistryKey<DroppableRegistration>;
12
14
  export interface DraggableRegistration {
@@ -26,6 +28,8 @@ export declare const RegistryContext: React.Context<RegistryContextValue | undef
26
28
  export interface RegistryProviderProps {
27
29
  children?: React.ReactNode;
28
30
  }
31
+ export declare function createRegistry(): RegistryContextValue;
32
+ export declare const GlobalRegistry: RegistryContextValue;
29
33
  export declare function RegistryProvider(props: RegistryProviderProps): React.JSX.Element;
30
34
  export declare function useRegistryRegistration<T extends defined>(key: RegistryKey<T>, createRegistration: (guiObject: GuiObject) => T, dependencies: React.DependencyList): {
31
35
  ref: React.Dispatch<React.SetStateAction<GuiObject | undefined>>;
@@ -9,18 +9,16 @@ local DraggableRegistryKey = {
9
9
  name = "Draggable",
10
10
  }
11
11
  local RegistryContext = React.createContext(nil)
12
- local function RegistryProvider(props)
13
- local entries = React.useRef({})
12
+ local function createRegistry()
13
+ local entries = {}
14
14
  local register = function(guiObject, key, value)
15
- local _current = entries.current
16
15
  local _name = key.name
17
- local keyEntries = _current[_name]
16
+ local keyEntries = entries[_name]
18
17
  if keyEntries == nil then
19
18
  keyEntries = {}
20
- local _current_1 = entries.current
21
19
  local _name_1 = key.name
22
20
  local _keyEntries = keyEntries
23
- _current_1[_name_1] = _keyEntries
21
+ entries[_name_1] = _keyEntries
24
22
  end
25
23
  local _keyEntries = keyEntries
26
24
  local _guiObject = guiObject
@@ -28,9 +26,8 @@ local function RegistryProvider(props)
28
26
  _keyEntries[_guiObject] = _value
29
27
  end
30
28
  local unregister = function(guiObject, key)
31
- local _current = entries.current
32
29
  local _name = key.name
33
- local keyEntries = _current[_name]
30
+ local keyEntries = entries[_name]
34
31
  if keyEntries == nil then
35
32
  return nil
36
33
  end
@@ -43,15 +40,13 @@ local function RegistryProvider(props)
43
40
  end
44
41
  -- ▲ ReadonlyMap.size ▲
45
42
  if _size == 0 then
46
- local _current_1 = entries.current
47
43
  local _name_1 = key.name
48
- _current_1[_name_1] = nil
44
+ entries[_name_1] = nil
49
45
  end
50
46
  end
51
47
  local get = function(guiObject, key)
52
- local _current = entries.current
53
48
  local _name = key.name
54
- local _result = _current[_name]
49
+ local _result = entries[_name]
55
50
  if _result ~= nil then
56
51
  local _guiObject = guiObject
57
52
  _result = _result[_guiObject]
@@ -59,9 +54,8 @@ local function RegistryProvider(props)
59
54
  return _result
60
55
  end
61
56
  local getAll = function(key)
62
- local _current = entries.current
63
57
  local _name = key.name
64
- local keyEntries = _current[_name]
58
+ local keyEntries = entries[_name]
65
59
  if keyEntries == nil then
66
60
  return {}
67
61
  end
@@ -74,13 +68,17 @@ local function RegistryProvider(props)
74
68
  local GetNextId = function()
75
69
  return HttpService:GenerateGUID(false)
76
70
  end
77
- local contextValue = {
71
+ return {
78
72
  register = register,
79
73
  unregister = unregister,
80
74
  get = get,
81
75
  getAll = getAll,
82
76
  GetNextId = GetNextId,
83
77
  }
78
+ end
79
+ local GlobalRegistry = createRegistry()
80
+ local function RegistryProvider(props)
81
+ local contextValue = React.useState(createRegistry)
84
82
  return React.createElement(RegistryContext.Provider, {
85
83
  value = contextValue,
86
84
  }, props.children)
@@ -114,9 +112,11 @@ local function useRegistryRegistration(key, createRegistration, dependencies)
114
112
  }
115
113
  end
116
114
  return {
115
+ createRegistry = createRegistry,
117
116
  RegistryProvider = RegistryProvider,
118
117
  useRegistryRegistration = useRegistryRegistration,
119
118
  DroppableRegistryKey = DroppableRegistryKey,
120
119
  DraggableRegistryKey = DraggableRegistryKey,
121
120
  RegistryContext = RegistryContext,
121
+ GlobalRegistry = GlobalRegistry,
122
122
  }
@@ -388,6 +388,15 @@ local WoodenTheme = createTheme({
388
388
  },
389
389
  },
390
390
  },
391
+ draggable = {
392
+ placeholder = {
393
+ backgroundColor = Color3.fromHex("#3D2712"),
394
+ backgroundTransparency = 0.35,
395
+ borderColor = Color3.fromHex("#A16B30"),
396
+ borderThickness = 2,
397
+ cornerRadius = 0,
398
+ },
399
+ },
391
400
  box = {
392
401
  borderThickness = 0,
393
402
  boxShadow = 0,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rbxts/react-clean-ui",
3
- "version": "1.2.9",
3
+ "version": "1.4.0",
4
4
  "description": "A clean UI library for Roblox TypeScript projects",
5
5
  "main": "out/init.lua",
6
6
  "scripts": {