@rbxts/uiblox 0.2.0-alpha.35 → 0.2.0-alpha.36

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.
@@ -11,6 +11,7 @@ export * from "./layout/index";
11
11
  export * from "./preloader/index";
12
12
  export * from "./progressBar/index";
13
13
  export * from "./scroll/index";
14
+ export * from "./reorder/index";
14
15
  export * from "./shadow/index";
15
16
  export * from "./sidebar/index";
16
17
  export * from "./toast/index";
@@ -40,6 +40,9 @@ end
40
40
  for _k, _v in TS.import(script, script, "scroll") or {} do
41
41
  exports[_k] = _v
42
42
  end
43
+ for _k, _v in TS.import(script, script, "reorder") or {} do
44
+ exports[_k] = _v
45
+ end
43
46
  for _k, _v in TS.import(script, script, "shadow") or {} do
44
47
  exports[_k] = _v
45
48
  end
@@ -0,0 +1,2 @@
1
+ export { DragRect, hitRect, isReorderMove, isReorderPress, isReorderRelease, passedDragThreshold, placeItem, REORDER_THRESHOLD, transferId } from "./reorder";
2
+ export { ReorderDragHandle, ReorderDragState, useReorderDrag } from "./useReorderDrag";
@@ -0,0 +1,14 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local TS = _G[script]
3
+ local exports = {}
4
+ local _reorder = TS.import(script, script, "reorder")
5
+ exports.hitRect = _reorder.hitRect
6
+ exports.isReorderMove = _reorder.isReorderMove
7
+ exports.isReorderPress = _reorder.isReorderPress
8
+ exports.isReorderRelease = _reorder.isReorderRelease
9
+ exports.passedDragThreshold = _reorder.passedDragThreshold
10
+ exports.placeItem = _reorder.placeItem
11
+ exports.REORDER_THRESHOLD = _reorder.REORDER_THRESHOLD
12
+ exports.transferId = _reorder.transferId
13
+ exports.useReorderDrag = TS.import(script, script, "useReorderDrag").useReorderDrag
14
+ return exports
@@ -0,0 +1,24 @@
1
+ export declare const REORDER_THRESHOLD = 6;
2
+ export interface DragRect {
3
+ id: string;
4
+ x: number;
5
+ y: number;
6
+ width: number;
7
+ height: number;
8
+ }
9
+ export declare function isReorderPress(kind: Enum.UserInputType): boolean;
10
+ export declare function isReorderMove(kind: Enum.UserInputType): boolean;
11
+ export declare function isReorderRelease(kind: Enum.UserInputType): boolean;
12
+ export declare function passedDragThreshold(startX: number, startY: number, x: number, y: number, threshold?: number): boolean;
13
+ /** Smallest rect containing the point wins, so a card beats the column behind it. */
14
+ export declare function hitRect(rects: readonly DragRect[], x: number, y: number): string | undefined;
15
+ /** Final index after the move. Out-of-range or a no-op returns a copy. */
16
+ export declare function placeItem<T extends defined>(items: readonly T[], from: number, to: number): T[];
17
+ /**
18
+ * Insert `id` at `index` in `dest` and remove it from `source`.
19
+ * The same list uses placeItem, where index is the final index.
20
+ */
21
+ export declare function transferId(source: readonly string[], dest: readonly string[], id: string, index: number): {
22
+ source: string[];
23
+ dest: string[];
24
+ };
@@ -0,0 +1,178 @@
1
+ -- Compiled with roblox-ts v3.0.0
2
+ local REORDER_THRESHOLD = 6
3
+ local function isReorderPress(kind)
4
+ return kind == Enum.UserInputType.MouseButton1 or kind == Enum.UserInputType.Touch
5
+ end
6
+ local function isReorderMove(kind)
7
+ return kind == Enum.UserInputType.MouseMovement or kind == Enum.UserInputType.Touch
8
+ end
9
+ local function isReorderRelease(kind)
10
+ return kind == Enum.UserInputType.MouseButton1 or kind == Enum.UserInputType.Touch
11
+ end
12
+ local function passedDragThreshold(startX, startY, x, y, threshold)
13
+ if threshold == nil then
14
+ threshold = REORDER_THRESHOLD
15
+ end
16
+ local dx = x - startX
17
+ local dy = y - startY
18
+ return dx * dx + dy * dy >= threshold * threshold
19
+ end
20
+ --* Smallest rect containing the point wins, so a card beats the column behind it.
21
+ local function hitRect(rects, x, y)
22
+ local best
23
+ local bestArea = math.huge
24
+ for _, rect in rects do
25
+ if x < rect.x or y < rect.y or x > rect.x + rect.width or y > rect.y + rect.height then
26
+ continue
27
+ end
28
+ local area = rect.width * rect.height
29
+ if area < bestArea then
30
+ best = rect
31
+ bestArea = area
32
+ end
33
+ end
34
+ local _result = best
35
+ if _result ~= nil then
36
+ _result = _result.id
37
+ end
38
+ return _result
39
+ end
40
+ --* Final index after the move. Out-of-range or a no-op returns a copy.
41
+ local function placeItem(items, from, to)
42
+ local listed = {}
43
+ for _, item in items do
44
+ table.insert(listed, item)
45
+ end
46
+ local count = #listed
47
+ if from < 0 or to < 0 or from >= count or to >= count or from == to then
48
+ return listed
49
+ end
50
+ local moved = listed[from + 1]
51
+ if from < to then
52
+ do
53
+ local index = from
54
+ local _shouldIncrement = false
55
+ while true do
56
+ if _shouldIncrement then
57
+ index += 1
58
+ else
59
+ _shouldIncrement = true
60
+ end
61
+ if not (index < to) then
62
+ break
63
+ end
64
+ listed[index + 1] = listed[index + 2]
65
+ end
66
+ end
67
+ else
68
+ do
69
+ local index = from
70
+ local _shouldIncrement = false
71
+ while true do
72
+ if _shouldIncrement then
73
+ index -= 1
74
+ else
75
+ _shouldIncrement = true
76
+ end
77
+ if not (index > to) then
78
+ break
79
+ end
80
+ listed[index + 1] = listed[index]
81
+ end
82
+ end
83
+ end
84
+ listed[to + 1] = moved
85
+ return listed
86
+ end
87
+ local function indexOfId(ids, id)
88
+ for index = 0, #ids - 1 do
89
+ if ids[index + 1] == id then
90
+ return index
91
+ end
92
+ end
93
+ return -1
94
+ end
95
+ --[[
96
+ *
97
+ * Insert `id` at `index` in `dest` and remove it from `source`.
98
+ * The same list uses placeItem, where index is the final index.
99
+
100
+ ]]
101
+ local function transferId(source, dest, id, index)
102
+ if source == dest then
103
+ local placed = placeItem(source, indexOfId(source, id), math.clamp(index, 0, math.max(0, #source - 1)))
104
+ return {
105
+ source = placed,
106
+ dest = placed,
107
+ }
108
+ end
109
+ local nextSource = {}
110
+ local found = false
111
+ for _, item in source do
112
+ if item == id then
113
+ found = true
114
+ else
115
+ table.insert(nextSource, item)
116
+ end
117
+ end
118
+ local nextDest = {}
119
+ for _, item in dest do
120
+ table.insert(nextDest, item)
121
+ end
122
+ if not found then
123
+ return {
124
+ source = nextSource,
125
+ dest = nextDest,
126
+ }
127
+ end
128
+ local at = math.clamp(math.floor(index), 0, #nextDest)
129
+ local inserted = {}
130
+ do
131
+ local cursor = 0
132
+ local _shouldIncrement = false
133
+ while true do
134
+ if _shouldIncrement then
135
+ cursor += 1
136
+ else
137
+ _shouldIncrement = true
138
+ end
139
+ if not (cursor < at) then
140
+ break
141
+ end
142
+ local _arg0 = nextDest[cursor + 1]
143
+ table.insert(inserted, _arg0)
144
+ end
145
+ end
146
+ local _id = id
147
+ table.insert(inserted, _id)
148
+ do
149
+ local cursor = at
150
+ local _shouldIncrement = false
151
+ while true do
152
+ if _shouldIncrement then
153
+ cursor += 1
154
+ else
155
+ _shouldIncrement = true
156
+ end
157
+ if not (cursor < #nextDest) then
158
+ break
159
+ end
160
+ local _arg0 = nextDest[cursor + 1]
161
+ table.insert(inserted, _arg0)
162
+ end
163
+ end
164
+ return {
165
+ source = nextSource,
166
+ dest = inserted,
167
+ }
168
+ end
169
+ return {
170
+ isReorderPress = isReorderPress,
171
+ isReorderMove = isReorderMove,
172
+ isReorderRelease = isReorderRelease,
173
+ passedDragThreshold = passedDragThreshold,
174
+ hitRect = hitRect,
175
+ placeItem = placeItem,
176
+ transferId = transferId,
177
+ REORDER_THRESHOLD = REORDER_THRESHOLD,
178
+ }
@@ -0,0 +1,15 @@
1
+ import { DragRect } from "./reorder";
2
+ export interface ReorderDragState {
3
+ active: boolean;
4
+ id?: string;
5
+ overId?: string;
6
+ x: number;
7
+ y: number;
8
+ }
9
+ export interface ReorderDragHandle {
10
+ drag: ReorderDragState;
11
+ begin: (id: string, input: InputObject) => boolean;
12
+ cancel: () => void;
13
+ suppressClick: () => boolean;
14
+ }
15
+ export declare function useReorderDrag(onDrop: (fromId: string, overId?: string) => void, getRects: () => readonly DragRect[]): ReorderDragHandle;
@@ -0,0 +1,129 @@
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 useEffect = _react.useEffect
5
+ local useRef = _react.useRef
6
+ local useState = _react.useState
7
+ local UserInputService = TS.import(script, TS.getModule(script, "@rbxts", "services")).UserInputService
8
+ local _reorder = TS.import(script, script.Parent, "reorder")
9
+ local hitRect = _reorder.hitRect
10
+ local isReorderMove = _reorder.isReorderMove
11
+ local isReorderPress = _reorder.isReorderPress
12
+ local isReorderRelease = _reorder.isReorderRelease
13
+ local passedDragThreshold = _reorder.passedDragThreshold
14
+ local rest = function()
15
+ return {
16
+ active = false,
17
+ x = 0,
18
+ y = 0,
19
+ }
20
+ end
21
+ local function useReorderDrag(onDrop, getRects)
22
+ local drag, setDrag = useState(rest())
23
+ local tracking = useRef({
24
+ down = false,
25
+ active = false,
26
+ x = 0,
27
+ y = 0,
28
+ startX = 0,
29
+ startY = 0,
30
+ })
31
+ local onDropRef = useRef(onDrop)
32
+ local rectsRef = useRef(getRects)
33
+ local took = useRef(false)
34
+ onDropRef.current = onDrop
35
+ rectsRef.current = getRects
36
+ local clear = function(drop)
37
+ local current = tracking.current
38
+ tracking.current = {
39
+ down = false,
40
+ active = false,
41
+ x = 0,
42
+ y = 0,
43
+ startX = 0,
44
+ startY = 0,
45
+ }
46
+ setDrag(rest())
47
+ if drop and current.active and current.id ~= nil then
48
+ took.current = true
49
+ onDropRef.current(current.id, current.overId)
50
+ end
51
+ end
52
+ useEffect(function()
53
+ local changed = UserInputService.InputChanged:Connect(function(input)
54
+ local current = tracking.current
55
+ if not current.down or not isReorderMove(input.UserInputType) then
56
+ return nil
57
+ end
58
+ local x = input.Position.X
59
+ local y = input.Position.Y
60
+ local active = current.active or passedDragThreshold(current.startX, current.startY, x, y)
61
+ local overId = if active then hitRect(rectsRef.current(), x, y) else nil
62
+ local _object = table.clone(current)
63
+ setmetatable(_object, nil)
64
+ _object.active = active
65
+ _object.x = x
66
+ _object.y = y
67
+ _object.overId = overId
68
+ tracking.current = _object
69
+ if active then
70
+ setDrag({
71
+ active = true,
72
+ id = current.id,
73
+ overId = overId,
74
+ x = x,
75
+ y = y,
76
+ })
77
+ end
78
+ end)
79
+ local ended = UserInputService.InputEnded:Connect(function(input)
80
+ if not tracking.current.down or not isReorderRelease(input.UserInputType) then
81
+ return nil
82
+ end
83
+ clear(true)
84
+ end)
85
+ local began = UserInputService.InputBegan:Connect(function(input)
86
+ if input.KeyCode == Enum.KeyCode.Escape then
87
+ clear(false)
88
+ end
89
+ end)
90
+ return function()
91
+ changed:Disconnect()
92
+ ended:Disconnect()
93
+ began:Disconnect()
94
+ end
95
+ end, {})
96
+ return {
97
+ drag = drag,
98
+ begin = function(id, input)
99
+ if not isReorderPress(input.UserInputType) then
100
+ return false
101
+ end
102
+ local x = input.Position.X
103
+ local y = input.Position.Y
104
+ tracking.current = {
105
+ down = true,
106
+ active = false,
107
+ id = id,
108
+ x = x,
109
+ y = y,
110
+ startX = x,
111
+ startY = y,
112
+ }
113
+ return true
114
+ end,
115
+ cancel = function()
116
+ return clear(false)
117
+ end,
118
+ suppressClick = function()
119
+ if not took.current then
120
+ return false
121
+ end
122
+ took.current = false
123
+ return true
124
+ end,
125
+ }
126
+ end
127
+ return {
128
+ useReorderDrag = useReorderDrag,
129
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rbxts/uiblox",
3
- "version": "0.2.0-alpha.35",
3
+ "version": "0.2.0-alpha.36",
4
4
  "description": "UI Library and theming for roblox-ts projects",
5
5
  "main": "out/init.luau",
6
6
  "packageManager": "pnpm@11.3.0",
@@ -8,7 +8,7 @@
8
8
  "build": "rbxtsc",
9
9
  "watch": "rbxtsc -w",
10
10
  "pack:check": "node scripts/pack-check.mjs",
11
- "test": "node scripts/no-internal-refs.check.mjs && node scripts/import-case.check.mjs && node --experimental-strip-types scripts/theme-scope.check.mjs && node --experimental-strip-types scripts/style-types.check.mjs && node --experimental-strip-types scripts/style-cache.check.mjs && node --experimental-strip-types scripts/style-variants.check.mjs && node --experimental-strip-types scripts/component-styles.check.mjs && node --experimental-strip-types scripts/interaction-styles.check.mjs && node --experimental-strip-types scripts/resolve-style.check.mjs && node --experimental-strip-types scripts/resolve-sx.check.mjs && node --experimental-strip-types scripts/sx-prop.check.mjs && node --experimental-strip-types scripts/style-system.check.mjs && node --experimental-strip-types scripts/host-sx.check.mjs && node --experimental-strip-types scripts/density.check.mjs && node --experimental-strip-types scripts/styles.check.mjs && node --experimental-strip-types scripts/contrast.check.mjs && node --experimental-strip-types scripts/primitives.check.mjs && node scripts/state-matrix-registers.check.mjs && node --experimental-strip-types scripts/paper.check.mjs && node --experimental-strip-types scripts/list-item.check.mjs && node --experimental-strip-types scripts/slider.check.mjs && node --experimental-strip-types scripts/input.check.mjs && node --experimental-strip-types scripts/menu.check.mjs && node --experimental-strip-types scripts/guard.check.mjs && node --experimental-strip-types scripts/breakpoints.check.mjs && node --experimental-strip-types scripts/viewport-observer.check.mjs && node --experimental-strip-types scripts/focus-trap.check.mjs && node --experimental-strip-types scripts/select-typeahead.check.mjs && node --experimental-strip-types scripts/select-groups.check.mjs && node --experimental-strip-types scripts/select-multi.check.mjs && node --experimental-strip-types scripts/select-polish.check.mjs && node --experimental-strip-types scripts/reduced-motion.check.mjs && node --experimental-strip-types scripts/card.check.mjs && node --experimental-strip-types scripts/chip.check.mjs && node --experimental-strip-types scripts/badge.check.mjs && node --experimental-strip-types scripts/avatar.check.mjs && node --experimental-strip-types scripts/imageList.check.mjs && node --experimental-strip-types scripts/drawer.check.mjs && node --experimental-strip-types scripts/breadcrumbs.check.mjs && node --experimental-strip-types scripts/pagination.check.mjs && node --experimental-strip-types scripts/stepper.check.mjs && node --experimental-strip-types scripts/accordion.check.mjs && node --experimental-strip-types scripts/snackbar.check.mjs && node --experimental-strip-types scripts/table.check.mjs && node --experimental-strip-types scripts/table-columns.check.mjs && node --experimental-strip-types scripts/autocomplete.check.mjs && node --experimental-strip-types scripts/field-loading.check.mjs && node --experimental-strip-types scripts/fab.check.mjs && node --experimental-strip-types scripts/appbar.check.mjs && node --experimental-strip-types scripts/bottom-navigation.check.mjs && node --experimental-strip-types scripts/alert.check.mjs && node --experimental-strip-types scripts/toggle-button.check.mjs && node --experimental-strip-types scripts/link.check.mjs && node --experimental-strip-types scripts/rating.check.mjs && node --experimental-strip-types scripts/stack.check.mjs && node --experimental-strip-types scripts/flex-item.check.mjs && node --experimental-strip-types scripts/grid.check.mjs && node --experimental-strip-types scripts/speed-dial.check.mjs && node --experimental-strip-types scripts/form-text.check.mjs && node --experimental-strip-types scripts/box.check.mjs && node --experimental-strip-types scripts/scroll-view.check.mjs && node --experimental-strip-types scripts/image-list.check.mjs && node --experimental-strip-types scripts/radio-group.check.mjs && node --experimental-strip-types scripts/container.check.mjs && node --experimental-strip-types scripts/divider.check.mjs && node --experimental-strip-types scripts/markdown.check.mjs && node --experimental-strip-types scripts/switch.check.mjs && node --experimental-strip-types scripts/tabs.check.mjs && node --experimental-strip-types scripts/dialog.check.mjs && node --experimental-strip-types scripts/backdrop.check.mjs && node --experimental-strip-types scripts/cframe-editor.check.mjs && node --experimental-strip-types scripts/enum-picker.check.mjs && node --experimental-strip-types scripts/number-range.check.mjs && node --experimental-strip-types scripts/date-range.check.mjs && node --experimental-strip-types scripts/sparkline.check.mjs && node --experimental-strip-types scripts/rect-editor.check.mjs && node --experimental-strip-types scripts/asset-field.check.mjs && node --experimental-strip-types scripts/gradient-editor.check.mjs && node --experimental-strip-types scripts/ray-editor.check.mjs && node --experimental-strip-types scripts/physical-properties.check.mjs && node --experimental-strip-types scripts/brickcolor-picker.check.mjs",
11
+ "test": "node scripts/no-internal-refs.check.mjs && node scripts/import-case.check.mjs && node --experimental-strip-types scripts/theme-scope.check.mjs && node --experimental-strip-types scripts/style-types.check.mjs && node --experimental-strip-types scripts/style-cache.check.mjs && node --experimental-strip-types scripts/style-variants.check.mjs && node --experimental-strip-types scripts/component-styles.check.mjs && node --experimental-strip-types scripts/interaction-styles.check.mjs && node --experimental-strip-types scripts/resolve-style.check.mjs && node --experimental-strip-types scripts/resolve-sx.check.mjs && node --experimental-strip-types scripts/sx-prop.check.mjs && node --experimental-strip-types scripts/style-system.check.mjs && node --experimental-strip-types scripts/host-sx.check.mjs && node --experimental-strip-types scripts/density.check.mjs && node --experimental-strip-types scripts/styles.check.mjs && node --experimental-strip-types scripts/contrast.check.mjs && node --experimental-strip-types scripts/primitives.check.mjs && node scripts/state-matrix-registers.check.mjs && node --experimental-strip-types scripts/paper.check.mjs && node --experimental-strip-types scripts/list-item.check.mjs && node --experimental-strip-types scripts/slider.check.mjs && node --experimental-strip-types scripts/input.check.mjs && node --experimental-strip-types scripts/menu.check.mjs && node --experimental-strip-types scripts/guard.check.mjs && node --experimental-strip-types scripts/breakpoints.check.mjs && node --experimental-strip-types scripts/viewport-observer.check.mjs && node --experimental-strip-types scripts/focus-trap.check.mjs && node --experimental-strip-types scripts/select-typeahead.check.mjs && node --experimental-strip-types scripts/select-groups.check.mjs && node --experimental-strip-types scripts/select-multi.check.mjs && node --experimental-strip-types scripts/select-polish.check.mjs && node --experimental-strip-types scripts/reduced-motion.check.mjs && node --experimental-strip-types scripts/card.check.mjs && node --experimental-strip-types scripts/chip.check.mjs && node --experimental-strip-types scripts/badge.check.mjs && node --experimental-strip-types scripts/avatar.check.mjs && node --experimental-strip-types scripts/imageList.check.mjs && node --experimental-strip-types scripts/drawer.check.mjs && node --experimental-strip-types scripts/breadcrumbs.check.mjs && node --experimental-strip-types scripts/pagination.check.mjs && node --experimental-strip-types scripts/stepper.check.mjs && node --experimental-strip-types scripts/accordion.check.mjs && node --experimental-strip-types scripts/snackbar.check.mjs && node --experimental-strip-types scripts/table.check.mjs && node --experimental-strip-types scripts/table-columns.check.mjs && node --experimental-strip-types scripts/reorder.check.mjs && node --experimental-strip-types scripts/autocomplete.check.mjs && node --experimental-strip-types scripts/field-loading.check.mjs && node --experimental-strip-types scripts/fab.check.mjs && node --experimental-strip-types scripts/appbar.check.mjs && node --experimental-strip-types scripts/bottom-navigation.check.mjs && node --experimental-strip-types scripts/alert.check.mjs && node --experimental-strip-types scripts/toggle-button.check.mjs && node --experimental-strip-types scripts/link.check.mjs && node --experimental-strip-types scripts/rating.check.mjs && node --experimental-strip-types scripts/stack.check.mjs && node --experimental-strip-types scripts/flex-item.check.mjs && node --experimental-strip-types scripts/grid.check.mjs && node --experimental-strip-types scripts/speed-dial.check.mjs && node --experimental-strip-types scripts/form-text.check.mjs && node --experimental-strip-types scripts/box.check.mjs && node --experimental-strip-types scripts/scroll-view.check.mjs && node --experimental-strip-types scripts/image-list.check.mjs && node --experimental-strip-types scripts/radio-group.check.mjs && node --experimental-strip-types scripts/container.check.mjs && node --experimental-strip-types scripts/divider.check.mjs && node --experimental-strip-types scripts/markdown.check.mjs && node --experimental-strip-types scripts/switch.check.mjs && node --experimental-strip-types scripts/tabs.check.mjs && node --experimental-strip-types scripts/dialog.check.mjs && node --experimental-strip-types scripts/backdrop.check.mjs && node --experimental-strip-types scripts/cframe-editor.check.mjs && node --experimental-strip-types scripts/enum-picker.check.mjs && node --experimental-strip-types scripts/number-range.check.mjs && node --experimental-strip-types scripts/date-range.check.mjs && node --experimental-strip-types scripts/sparkline.check.mjs && node --experimental-strip-types scripts/rect-editor.check.mjs && node --experimental-strip-types scripts/asset-field.check.mjs && node --experimental-strip-types scripts/gradient-editor.check.mjs && node --experimental-strip-types scripts/ray-editor.check.mjs && node --experimental-strip-types scripts/physical-properties.check.mjs && node --experimental-strip-types scripts/brickcolor-picker.check.mjs",
12
12
  "prepublishOnly": "pnpm build"
13
13
  },
14
14
  "keywords": [