@nrbx/topbar-components 1.0.0 → 1.0.1

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.
@@ -1,4 +1,4 @@
1
- -- Compiled with roblox-ts v1.0.2
1
+ -- Compiled with roblox-ts v3.0.0
2
2
  local TS = _G[script]
3
3
  local _pretty_react_hooks = TS.import(script, TS.getModule(script, "@rbxts", "pretty-react-hooks").out)
4
4
  local mapBinding = _pretty_react_hooks.mapBinding
@@ -1,4 +1,5 @@
1
1
  import React from '@rbxts/react';
2
+ export type Dock = 'Left' | 'Center' | 'Right';
2
3
  export interface IconProps extends React.PropsWithChildren {
3
4
  backgroundTransparency?: StateDependent<number>;
4
5
  backgroundColor?: StateDependent<Color3>;
@@ -24,6 +25,11 @@ export interface IconProps extends React.PropsWithChildren {
24
25
  textAlignment?: StateDependent<Enum.TextXAlignment>;
25
26
  richText?: StateDependent<boolean>;
26
27
  toggleStateOnClick?: boolean;
28
+ dock?: Dock;
29
+ /** When true, renders as a non-interactive label (no clicks, no hovers, no state changes) */
30
+ static?: boolean;
31
+ /** When true, dulls the text and icon with a dimming overlay */
32
+ disabled?: boolean;
27
33
  selected?: () => void;
28
34
  deselected?: () => void;
29
35
  hover?: () => void;
@@ -37,4 +43,4 @@ export type IconState = 'selected' | 'deselected';
37
43
  export type StateDependent<T> = Record<IconState, T> | T;
38
44
  export type FromStateDependent<T> = T extends StateDependent<infer U> ? U : T;
39
45
  export type IconId = number;
40
- export declare function Icon({ children, ...componentProps }: IconProps): React.JSX.Element;
46
+ export declare function Icon(componentProps: IconProps): React.JSX.Element;
@@ -1,4 +1,4 @@
1
- -- Compiled with roblox-ts v1.0.2
1
+ -- Compiled with roblox-ts v3.0.0
2
2
  local TS = _G[script]
3
3
  local deepEquals = TS.import(script, TS.getModule(script, "@rbxts", "object-utils")).deepEquals
4
4
  local _pretty_react_hooks = TS.import(script, TS.getModule(script, "@rbxts", "pretty-react-hooks").out)
@@ -24,18 +24,9 @@ local useId = TS.import(script, script.Parent.Parent, "hooks", "use-id").useId
24
24
  local noop = TS.import(script, script.Parent.Parent, "style").noop
25
25
  local stateful = TS.import(script, script.Parent.Parent, "utilities", "resolve-state-dependent").stateful
26
26
  local ANIMATEABLE = { "backgroundColor", "backgroundTransparency", "imageColor", "imageTransparency" }
27
- local function Icon(_param)
28
- local children = _param.children
29
- local _extracted = {
30
- ["children"] = true,
31
- }
32
- local _rest = {}
33
- for _k, _v in _param do
34
- if not _extracted[_k] then
35
- _rest[_k] = _v
36
- end
37
- end
38
- local componentProps = _rest
27
+ local function Icon(componentProps)
28
+ local _binding = componentProps
29
+ local children = _binding.children
39
30
  local inset = useGuiInset()
40
31
  local location = useLocation()
41
32
  local id = useId()
@@ -63,15 +54,24 @@ local function Icon(_param)
63
54
  end
64
55
  local props = _object_1
65
56
  useMountEffect(function()
57
+ if props.static then
58
+ return nil
59
+ end
66
60
  local _ = props.defaultState and not componentProps.forcedState and setState(props.defaultState)
67
61
  end)
68
62
  useEffect(function()
63
+ if props.static then
64
+ return nil
65
+ end
69
66
  if not componentProps.forcedState then
70
67
  return nil
71
68
  end
72
69
  setState(componentProps.forcedState)
73
70
  end, { componentProps.forcedState })
74
71
  useUpdateEffect(function()
72
+ if props.static then
73
+ return nil
74
+ end
75
75
  props.stateChanged(currentState)
76
76
  if currentState == "selected" then
77
77
  location.iconSelected(id)
@@ -82,6 +82,9 @@ local function Icon(_param)
82
82
  end
83
83
  end, { currentState })
84
84
  useUpdateEffect(function()
85
+ if props.static then
86
+ return nil
87
+ end
85
88
  if currentState == "selected" and not (table.find(location.selectedIcons, id) ~= nil) then
86
89
  setState("deselected")
87
90
  end
@@ -135,6 +138,9 @@ local function Icon(_param)
135
138
  local imagePos = stylesheet.sizing.imagePadding + imageSizeOff * -0.5
136
139
  local textLabelPos = UDim2.new(0, if currentImage ~= "" and currentImage then imageSize + stylesheet.sizing.imagePadding * 2 else stylesheet.sizing.labelPadding, 0.5, 0)
137
140
  useEffect(function()
141
+ if props.static then
142
+ return nil
143
+ end
138
144
  if location.type ~= "dropdown" then
139
145
  return nil
140
146
  end
@@ -144,6 +150,9 @@ local function Icon(_param)
144
150
  location.registerChild(id, _vector2 + _vector2_1)
145
151
  end, { currentState, contentSize.Y, dropdownAnimating, iconSize })
146
152
  useUnmountEffect(function()
153
+ if props.static then
154
+ return nil
155
+ end
147
156
  if location.type ~= "dropdown" then
148
157
  return nil
149
158
  end
@@ -169,8 +178,13 @@ local function Icon(_param)
169
178
  key = "IconWrapper",
170
179
  }, React.createElement("textbutton", {
171
180
  Size = UDim2.new(1, 0, 0, iconSize.Y),
181
+ Active = not props.static,
182
+ Selectable = not props.static,
172
183
  Event = {
173
184
  MouseButton1Click = function()
185
+ if props.static then
186
+ return nil
187
+ end
174
188
  if stateful(props.toggleStateOnClick, currentState) then
175
189
  setState(if currentState == "deselected" then "selected" else "deselected")
176
190
  end
@@ -182,6 +196,9 @@ local function Icon(_param)
182
196
  props.playSound(soundId)
183
197
  end,
184
198
  MouseButton2Click = function()
199
+ if props.static then
200
+ return nil
201
+ end
185
202
  if props.onRightClick == noop then
186
203
  return nil
187
204
  end
@@ -192,8 +209,8 @@ local function Icon(_param)
192
209
  end
193
210
  props.playSound(soundId)
194
211
  end,
195
- MouseEnter = props.hover,
196
- MouseLeave = props.unhover,
212
+ MouseEnter = if props.static then noop else props.hover,
213
+ MouseLeave = if props.static then noop else props.unhover,
197
214
  },
198
215
  Text = "",
199
216
  BackgroundTransparency = props.backgroundTransparency,
@@ -230,7 +247,14 @@ local function Icon(_param)
230
247
  }))), React.createElement("uicorner", {
231
248
  key = "UICorner",
232
249
  CornerRadius = if location.type == "dropdown" then stylesheet.dropdown.iconCornerRadius else stateful(props.cornerRadius, currentState),
233
- }))))
250
+ }), props.disabled and (React.createElement("frame", {
251
+ key = "DisabledOverlay",
252
+ Size = UDim2.fromScale(1, 1),
253
+ BackgroundTransparency = stylesheet.sizing.disabledOverlayTransparency,
254
+ BackgroundColor3 = stylesheet.sizing.disabledOverlayColor,
255
+ BorderSizePixel = 0,
256
+ ZIndex = 10,
257
+ })))))
234
258
  end
235
259
  return {
236
260
  Icon = Icon,
@@ -1,4 +1,4 @@
1
- -- Compiled with roblox-ts v1.0.2
1
+ -- Compiled with roblox-ts v3.0.0
2
2
  local TS = _G[script]
3
3
  local _react = TS.import(script, TS.getModule(script, "@rbxts", "react"))
4
4
  local React = _react
@@ -8,6 +8,30 @@ local LocationContext = _context.LocationContext
8
8
  local useStylesheet = _context.useStylesheet
9
9
  local useGuiInset = TS.import(script, script.Parent.Parent, "hooks", "use-gui-inset").useGuiInset
10
10
  local useVoicechatEnabled = TS.import(script, script.Parent.Parent, "hooks", "use-voicechat-enabled").useVoicechatEnabled
11
+ local function sortByDock(children)
12
+ local left = {}
13
+ local center = {}
14
+ local right = {}
15
+ local li = 0
16
+ local ci = 0
17
+ local ri = 0
18
+ React.Children.forEach(children, function(child)
19
+ if child == nil then
20
+ return nil
21
+ end
22
+ if React.isValidElement(child) and (child.props).dock == "Center" then
23
+ center[ci + 1] = child
24
+ ci += 1
25
+ elseif React.isValidElement(child) and (child.props).dock == "Right" then
26
+ right[ri + 1] = child
27
+ ri += 1
28
+ else
29
+ left[li + 1] = child
30
+ li += 1
31
+ end
32
+ end)
33
+ return { left, center, right }
34
+ end
11
35
  local function TopbarProvider(_param)
12
36
  local selectionMode = _param.selectionMode
13
37
  if selectionMode == nil then
@@ -22,6 +46,12 @@ local function TopbarProvider(_param)
22
46
  local hasBetaLabel = gameVoiceChatEnabled and voiceChatEnabled
23
47
  local leftPadding = if hasBetaLabel then stylesheet.paddingLeft + 16 else stylesheet.paddingLeft
24
48
  local frameHeight = inset.Height - stylesheet.insetHeightOffset
49
+ local _binding = sortByDock(children)
50
+ local leftChildren = _binding[1]
51
+ local centerChildren = _binding[2]
52
+ local rightChildren = _binding[3]
53
+ local hasCenter = #centerChildren > 0
54
+ local hasRight = #rightChildren > 0
25
55
  return React.createElement(LocationContext.Provider, {
26
56
  value = {
27
57
  type = "provider",
@@ -80,12 +110,45 @@ local function TopbarProvider(_param)
80
110
  PaddingRight = UDim.new(0, stylesheet.paddingRight),
81
111
  PaddingTop = UDim.new(0, stylesheet.paddingTop),
82
112
  PaddingBottom = UDim.new(0, stylesheet.paddingBottom),
113
+ }), React.createElement("frame", {
114
+ key = "LeftDock",
115
+ BackgroundTransparency = 1,
116
+ AnchorPoint = Vector2.new(0, 0.5),
117
+ Position = UDim2.new(0, 0, 0.5, 0),
118
+ Size = UDim2.fromScale(0, 1),
119
+ AutomaticSize = Enum.AutomaticSize.X,
120
+ }, React.createElement("uilistlayout", {
121
+ FillDirection = Enum.FillDirection.Horizontal,
122
+ SortOrder = Enum.SortOrder.LayoutOrder,
123
+ Padding = UDim.new(0, stylesheet.iconSpacing),
124
+ }), leftChildren), hasCenter and (React.createElement("frame", {
125
+ key = "CenterDock",
126
+ BackgroundTransparency = 1,
127
+ AnchorPoint = Vector2.new(0.5, 0.5),
128
+ Position = UDim2.new(0.5, 0, 0.5, 0),
129
+ Size = UDim2.fromScale(0, 1),
130
+ AutomaticSize = Enum.AutomaticSize.X,
131
+ }, React.createElement("uipadding", {
132
+ PaddingLeft = UDim.new(0, stylesheet.iconGroupSpacing),
133
+ PaddingRight = UDim.new(0, stylesheet.iconGroupSpacing),
134
+ }), React.createElement("uilistlayout", {
135
+ FillDirection = Enum.FillDirection.Horizontal,
136
+ SortOrder = Enum.SortOrder.LayoutOrder,
137
+ Padding = UDim.new(0, stylesheet.iconSpacing),
138
+ }), centerChildren)), hasRight and (React.createElement("frame", {
139
+ key = "RightDock",
140
+ BackgroundTransparency = 1,
141
+ AnchorPoint = Vector2.new(1, 0.5),
142
+ Position = UDim2.new(1, 0, 0.5, 0),
143
+ Size = UDim2.fromScale(0, 1),
144
+ AutomaticSize = Enum.AutomaticSize.X,
145
+ }, React.createElement("uipadding", {
146
+ PaddingLeft = UDim.new(0, stylesheet.iconGroupSpacing),
83
147
  }), React.createElement("uilistlayout", {
84
- key = "UIListLayout",
85
148
  FillDirection = Enum.FillDirection.Horizontal,
86
149
  SortOrder = Enum.SortOrder.LayoutOrder,
87
150
  Padding = UDim.new(0, stylesheet.iconSpacing),
88
- }), children))
151
+ }), rightChildren))))
89
152
  end
90
153
  return {
91
154
  TopbarProvider = TopbarProvider,
@@ -1,4 +1,4 @@
1
- -- Compiled with roblox-ts v1.0.2
1
+ -- Compiled with roblox-ts v3.0.0
2
2
  local TS = _G[script]
3
3
  local React = TS.import(script, TS.getModule(script, "@rbxts", "react"))
4
4
  local StylesheetContext = TS.import(script, script.Parent.Parent, "context").StylesheetContext
package/out/context.luau CHANGED
@@ -1,4 +1,4 @@
1
- -- Compiled with roblox-ts v1.0.2
1
+ -- Compiled with roblox-ts v3.0.0
2
2
  local TS = _G[script]
3
3
  local _react = TS.import(script, TS.getModule(script, "@rbxts", "react"))
4
4
  local createContext = _react.createContext
@@ -1,4 +1,4 @@
1
- -- Compiled with roblox-ts v1.0.2
1
+ -- Compiled with roblox-ts v3.0.0
2
2
  local TS = _G[script]
3
3
  local Object = TS.import(script, TS.getModule(script, "@rbxts", "object-utils"))
4
4
  local _pretty_react_hooks = TS.import(script, TS.getModule(script, "@rbxts", "pretty-react-hooks").out)
@@ -1,4 +1,4 @@
1
- -- Compiled with roblox-ts v1.0.2
1
+ -- Compiled with roblox-ts v3.0.0
2
2
  local TS = _G[script]
3
3
  local _pretty_react_hooks = TS.import(script, TS.getModule(script, "@rbxts", "pretty-react-hooks").out)
4
4
  local useEventListener = _pretty_react_hooks.useEventListener
@@ -1,4 +1,4 @@
1
- -- Compiled with roblox-ts v1.0.2
1
+ -- Compiled with roblox-ts v3.0.0
2
2
  local TS = _G[script]
3
3
  local useMemo = TS.import(script, TS.getModule(script, "@rbxts", "react")).useMemo
4
4
  local createIdGenerator = TS.import(script, script.Parent.Parent, "utilities", "id-gen").createIdGenerator
@@ -1,4 +1,4 @@
1
- -- Compiled with roblox-ts v1.0.2
1
+ -- Compiled with roblox-ts v3.0.0
2
2
  local TS = _G[script]
3
3
  local useAsyncEffect = TS.import(script, TS.getModule(script, "@rbxts", "pretty-react-hooks").out).useAsyncEffect
4
4
  local useState = TS.import(script, TS.getModule(script, "@rbxts", "react")).useState
package/out/init.luau CHANGED
@@ -1,4 +1,4 @@
1
- -- Compiled with roblox-ts v1.0.2
1
+ -- Compiled with roblox-ts v3.0.0
2
2
  local TS = _G[script]
3
3
  local exports = {}
4
4
  for _k, _v in TS.import(script, script, "components", "dropdown") or {} do
package/out/style.d.ts CHANGED
@@ -21,6 +21,8 @@ export interface Stylesheet {
21
21
  sizeScale: Vector2;
22
22
  /** Offset subtracted from the gui inset height */
23
23
  insetHeightOffset: number;
24
+ /** Extra gap between left, center, and right icon groups (default 0) */
25
+ iconGroupSpacing: number;
24
26
  };
25
27
  /**
26
28
  * Fine-grained sizing & layout overrides for icon internals.
@@ -43,6 +45,10 @@ export interface Stylesheet {
43
45
  minLabelWidthPadding: number;
44
46
  /** Fraction of icon height used for the text button label size (default 0.8) */
45
47
  buttonLabelHeightFraction: number;
48
+ /** Transparency of the dimming overlay when an icon is disabled (0 = fully visible, 1 = fully hidden) */
49
+ disabledOverlayTransparency: number;
50
+ /** Color of the dimming overlay when an icon is disabled */
51
+ disabledOverlayColor: Color3;
46
52
  };
47
53
  /**
48
54
  * Visual theming for the dropdown surface (background, border, position).
package/out/style.luau CHANGED
@@ -1,4 +1,4 @@
1
- -- Compiled with roblox-ts v1.0.2
1
+ -- Compiled with roblox-ts v3.0.0
2
2
  local TS = _G[script]
3
3
  local SoundService = TS.import(script, TS.getModule(script, "@rbxts", "services")).SoundService
4
4
  local function defaultPlaySound(id)
@@ -48,6 +48,9 @@ local DefaultStylesheet = {
48
48
  defaultState = "deselected",
49
49
  forcedState = "deselected",
50
50
  toggleStateOnClick = true,
51
+ dock = "Left",
52
+ static = false,
53
+ disabled = false,
51
54
  selected = noop,
52
55
  deselected = noop,
53
56
  stateChanged = noop,
@@ -85,6 +88,7 @@ local DefaultStylesheet = {
85
88
  position = UDim2.fromScale(1, 0),
86
89
  sizeScale = Vector2.new(1, 1),
87
90
  insetHeightOffset = 0,
91
+ iconGroupSpacing = 0,
88
92
  },
89
93
  sizing = {
90
94
  iconHeight = nil,
@@ -94,6 +98,8 @@ local DefaultStylesheet = {
94
98
  textMeasurementWidth = 99999,
95
99
  minLabelWidthPadding = 12,
96
100
  buttonLabelHeightFraction = 0.8,
101
+ disabledOverlayTransparency = 0.55,
102
+ disabledOverlayColor = Color3.new(0, 0, 0),
97
103
  },
98
104
  dropdownTheme = {
99
105
  backgroundColor = Color3.new(1, 1, 1),
@@ -1,4 +1,4 @@
1
- -- Compiled with roblox-ts v1.0.2
1
+ -- Compiled with roblox-ts v3.0.0
2
2
  local function createIdGenerator()
3
3
  local value = 0
4
4
  return function()
@@ -1,4 +1,4 @@
1
- -- Compiled with roblox-ts v1.0.2
1
+ -- Compiled with roblox-ts v3.0.0
2
2
  local TS = _G[script]
3
3
  local t = TS.import(script, TS.getModule(script, "@rbxts", "t").lib.ts).t
4
4
  local state_check = t.union(t.literal("selected"), t.literal("deselected"))
@@ -1,4 +1,4 @@
1
- -- Compiled with roblox-ts v1.0.2
1
+ -- Compiled with roblox-ts v3.0.0
2
2
  local TS = _G[script]
3
3
  local config = TS.import(script, TS.getModule(script, "@rbxts", "ripple").src).config
4
4
  local _object = table.clone(config.spring)
@@ -1,2 +1,2 @@
1
- -- Compiled with roblox-ts v1.0.2
1
+ -- Compiled with roblox-ts v3.0.0
2
2
  return nil
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nrbx/topbar-components",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "main": "out/init.lua",
5
5
  "scripts": {
6
6
  "build": "rbxtsc",
@@ -10,7 +10,7 @@
10
10
  "keywords": [],
11
11
  "author": "ninjaninja140",
12
12
  "license": "MIT",
13
- "description": "@rbxts/react component package mimicking topbar-plus",
13
+ "description": "@rbxts/react component package mimicking topbar-plus with extra functionality, forked from @rbxts/topbar-components",
14
14
  "types": "out/index.d.ts",
15
15
  "files": [
16
16
  "out",
@@ -30,7 +30,7 @@
30
30
  "@rbxts/compiler-types": "^3.0.0-types.0",
31
31
  "@rbxts/react": "^17.3.7-ts.2",
32
32
  "@rbxts/types": "^1.0.925",
33
- "roblox-ts": "npm:@wad4444/roblox-ts@^1.0.0",
33
+ "roblox-ts": "^3.0.0",
34
34
  "typescript": "^6.0.3"
35
35
  },
36
36
  "dependencies": {