@lattice-ui/accordion 0.5.0-next.2 → 0.5.0-next.3

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.
@@ -8,60 +8,104 @@ local _motion = TS.import(script, TS.getModule(script, "@lattice-ui", "motion").
8
8
  local createSurfaceRevealRecipe = _motion.createSurfaceRevealRecipe
9
9
  local usePresenceMotionController = _motion.usePresenceMotionController
10
10
  local useAccordionItemContext = TS.import(script, script.Parent, "context").useAccordionItemContext
11
+ local function getImplRestProps(props)
12
+ local restProps = {}
13
+ for rawKey, value in pairs(props) do
14
+ if not (type(rawKey) == "string") then
15
+ continue
16
+ end
17
+ if rawKey == "present" or rawKey == "forceMount" or rawKey == "transition" or rawKey == "onExitComplete" or rawKey == "asChild" or rawKey == "children" then
18
+ continue
19
+ end
20
+ restProps[rawKey] = value
21
+ end
22
+ return restProps
23
+ end
24
+ local function getContentRestProps(props)
25
+ local restProps = {}
26
+ for rawKey, value in pairs(props) do
27
+ if not (type(rawKey) == "string") then
28
+ continue
29
+ end
30
+ if rawKey == "asChild" or rawKey == "forceMount" or rawKey == "transition" or rawKey == "children" then
31
+ continue
32
+ end
33
+ restProps[rawKey] = value
34
+ end
35
+ return restProps
36
+ end
11
37
  local function AccordionContentImpl(props)
38
+ local present = props.present
39
+ local forceMount = props.forceMount
40
+ local transition = props.transition
41
+ local onExitComplete = props.onExitComplete
42
+ local asChild = props.asChild
43
+ local children = props.children
44
+ local restProps = getImplRestProps(props)
12
45
  local defaultTransition = React.useMemo(function()
13
46
  return createSurfaceRevealRecipe()
14
47
  end, {})
15
- local config = props.transition or defaultTransition
48
+ local config = transition or defaultTransition
16
49
  local motion = usePresenceMotionController({
17
- present = props.present,
18
- forceMount = props.forceMount,
50
+ present = present,
51
+ forceMount = forceMount,
19
52
  config = config,
20
- onExitComplete = props.onExitComplete,
53
+ onExitComplete = onExitComplete,
21
54
  })
22
55
  local mounted = motion.mounted
23
56
  local visible = mounted and (motion.present or motion.phase ~= "exited")
24
57
  if not mounted then
25
58
  return nil
26
59
  end
27
- if props.asChild then
28
- local child = props.children
29
- if not React.isValidElement(child) then
30
- error("[AccordionContent] `asChild` requires a child element.")
60
+ if asChild then
61
+ local child = children
62
+ if React.Children.count(children) ~= 1 or not React.isValidElement(child) then
63
+ error("[AccordionContent] `asChild` requires a single child element.")
31
64
  end
32
- return React.createElement(Slot, {
33
- Visible = visible,
34
- ref = motion.ref,
35
- }, child)
65
+ local _attributes = table.clone(restProps)
66
+ setmetatable(_attributes, nil)
67
+ _attributes.Visible = visible
68
+ _attributes.ref = motion.ref
69
+ return React.createElement(Slot, _attributes, child)
36
70
  end
37
- return React.createElement("frame", {
71
+ local _attributes = {
38
72
  BackgroundColor3 = Color3.fromRGB(35, 41, 54),
39
73
  BorderSizePixel = 0,
40
- Size = UDim2.fromOffset(260, 44),
41
- Visible = visible,
42
- ref = motion.ref,
43
- }, props.children)
74
+ }
75
+ for _k, _v in restProps do
76
+ _attributes[_k] = _v
77
+ end
78
+ _attributes.Visible = visible
79
+ _attributes.ref = motion.ref
80
+ return React.createElement("frame", _attributes, children)
44
81
  end
45
82
  local function AccordionContent(props)
46
83
  local itemContext = useAccordionItemContext()
47
- local forceMount = props.forceMount == true
48
- if forceMount then
49
- return React.createElement(AccordionContentImpl, {
50
- asChild = props.asChild,
51
- forceMount = true,
52
- present = itemContext.open,
53
- transition = props.transition,
54
- }, props.children)
84
+ local asChild = props.asChild
85
+ local forceMount = props.forceMount
86
+ local transition = props.transition
87
+ local children = props.children
88
+ local restProps = getContentRestProps(props)
89
+ local shouldForceMount = forceMount == true
90
+ if shouldForceMount then
91
+ local _attributes = table.clone(restProps)
92
+ setmetatable(_attributes, nil)
93
+ _attributes.asChild = asChild
94
+ _attributes.forceMount = true
95
+ _attributes.present = itemContext.open
96
+ _attributes.transition = transition
97
+ return React.createElement(AccordionContentImpl, _attributes, children)
55
98
  end
56
99
  return React.createElement(Presence, {
57
100
  present = itemContext.open,
58
101
  render = function(state)
59
- return React.createElement(AccordionContentImpl, {
60
- asChild = props.asChild,
61
- onExitComplete = state.onExitComplete,
62
- present = state.isPresent,
63
- transition = props.transition,
64
- }, props.children)
102
+ local _attributes = table.clone(restProps)
103
+ setmetatable(_attributes, nil)
104
+ _attributes.asChild = asChild
105
+ _attributes.onExitComplete = state.onExitComplete
106
+ _attributes.present = state.isPresent
107
+ _attributes.transition = transition
108
+ return React.createElement(AccordionContentImpl, _attributes, children)
65
109
  end,
66
110
  })
67
111
  end
@@ -33,9 +33,11 @@ export type AccordionTriggerProps = {
33
33
  asChild?: boolean;
34
34
  children?: React.ReactElement;
35
35
  };
36
+ type AccordionContentGuiProps = React.Attributes & Record<string, unknown>;
36
37
  export type AccordionContentProps = {
37
38
  asChild?: boolean;
38
39
  forceMount?: boolean;
39
40
  transition?: PresenceMotionConfig;
40
41
  children?: React.ReactNode;
41
- };
42
+ } & AccordionContentGuiProps;
43
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lattice-ui/accordion",
3
- "version": "0.5.0-next.2",
3
+ "version": "0.5.0-next.3",
4
4
  "private": false,
5
5
  "main": "out/init.luau",
6
6
  "types": "out/index.d.ts",
@@ -16,9 +16,9 @@
16
16
  "url": "https://github.com/astra-void/lattice-ui.git"
17
17
  },
18
18
  "dependencies": {
19
- "@lattice-ui/core": "0.5.0-next.2",
20
- "@lattice-ui/motion": "0.5.0-next.2",
21
- "@lattice-ui/layer": "0.5.0-next.2"
19
+ "@lattice-ui/core": "0.5.0-next.3",
20
+ "@lattice-ui/layer": "0.5.0-next.3",
21
+ "@lattice-ui/motion": "0.5.0-next.3"
22
22
  },
23
23
  "devDependencies": {
24
24
  "@rbxts/react": "17.3.7-ts.1",
@@ -30,8 +30,8 @@
30
30
  },
31
31
  "scripts": {
32
32
  "build": "rbxtsc -p tsconfig.json",
33
- "lint": "eslint .",
34
- "lint:fix": "eslint . --fix",
33
+ "lint": "biome check src",
34
+ "lint:fix": "biome check src --write --unsafe",
35
35
  "typecheck": "tsc -p tsconfig.typecheck.json",
36
36
  "watch": "rbxtsc -p tsconfig.json -w"
37
37
  }
@@ -1,25 +1,76 @@
1
1
  import { React, Slot } from "@lattice-ui/core";
2
2
  import { Presence } from "@lattice-ui/layer";
3
- import { createSurfaceRevealRecipe, type PresenceMotionConfig, usePresenceMotionController } from "@lattice-ui/motion";
3
+ import { createSurfaceRevealRecipe, usePresenceMotionController } from "@lattice-ui/motion";
4
4
  import { useAccordionItemContext } from "./context";
5
5
  import type { AccordionContentProps } from "./types";
6
6
 
7
- function AccordionContentImpl(props: {
7
+ type GuiPropBag = React.Attributes & Record<string, unknown>;
8
+
9
+ type AccordionContentImplProps = AccordionContentProps & {
8
10
  present: boolean;
9
- forceMount?: boolean;
10
- transition?: PresenceMotionConfig;
11
11
  onExitComplete?: () => void;
12
- asChild?: boolean;
13
- children?: React.ReactNode;
14
- }) {
12
+ };
13
+
14
+ function getImplRestProps(props: AccordionContentImplProps): GuiPropBag {
15
+ const restProps: GuiPropBag = {};
16
+
17
+ for (const [rawKey, value] of pairs(props as Record<string, unknown>)) {
18
+ if (!typeIs(rawKey, "string")) {
19
+ continue;
20
+ }
21
+
22
+ if (
23
+ rawKey === "present" ||
24
+ rawKey === "forceMount" ||
25
+ rawKey === "transition" ||
26
+ rawKey === "onExitComplete" ||
27
+ rawKey === "asChild" ||
28
+ rawKey === "children"
29
+ ) {
30
+ continue;
31
+ }
32
+
33
+ restProps[rawKey] = value;
34
+ }
35
+
36
+ return restProps;
37
+ }
38
+
39
+ function getContentRestProps(props: AccordionContentProps): GuiPropBag {
40
+ const restProps: GuiPropBag = {};
41
+
42
+ for (const [rawKey, value] of pairs(props as Record<string, unknown>)) {
43
+ if (!typeIs(rawKey, "string")) {
44
+ continue;
45
+ }
46
+
47
+ if (rawKey === "asChild" || rawKey === "forceMount" || rawKey === "transition" || rawKey === "children") {
48
+ continue;
49
+ }
50
+
51
+ restProps[rawKey] = value;
52
+ }
53
+
54
+ return restProps;
55
+ }
56
+
57
+ function AccordionContentImpl(props: AccordionContentImplProps) {
58
+ const present = props.present;
59
+ const forceMount = props.forceMount;
60
+ const transition = props.transition;
61
+ const onExitComplete = props.onExitComplete;
62
+ const asChild = props.asChild;
63
+ const children = props.children;
64
+ const restProps = getImplRestProps(props);
65
+
15
66
  const defaultTransition = React.useMemo(() => createSurfaceRevealRecipe(), []);
16
- const config = props.transition ?? defaultTransition;
67
+ const config = transition ?? defaultTransition;
17
68
 
18
69
  const motion = usePresenceMotionController<Frame>({
19
- present: props.present,
20
- forceMount: props.forceMount,
70
+ present,
71
+ forceMount,
21
72
  config,
22
- onExitComplete: props.onExitComplete,
73
+ onExitComplete,
23
74
  });
24
75
 
25
76
  const mounted = motion.mounted;
@@ -29,14 +80,14 @@ function AccordionContentImpl(props: {
29
80
  return undefined;
30
81
  }
31
82
 
32
- if (props.asChild) {
33
- const child = props.children;
34
- if (!React.isValidElement(child)) {
35
- error("[AccordionContent] `asChild` requires a child element.");
83
+ if (asChild) {
84
+ const child = children;
85
+ if (React.Children.count(children) !== 1 || !React.isValidElement(child)) {
86
+ error("[AccordionContent] `asChild` requires a single child element.");
36
87
  }
37
88
 
38
89
  return (
39
- <Slot Visible={visible} ref={motion.ref}>
90
+ <Slot {...restProps} Visible={visible} ref={motion.ref}>
40
91
  {child}
41
92
  </Slot>
42
93
  );
@@ -46,28 +97,35 @@ function AccordionContentImpl(props: {
46
97
  <frame
47
98
  BackgroundColor3={Color3.fromRGB(35, 41, 54)}
48
99
  BorderSizePixel={0}
49
- Size={UDim2.fromOffset(260, 44)}
100
+ {...restProps}
50
101
  Visible={visible}
51
102
  ref={motion.ref}
52
103
  >
53
- {props.children}
104
+ {children}
54
105
  </frame>
55
106
  );
56
107
  }
57
108
 
58
109
  export function AccordionContent(props: AccordionContentProps) {
59
110
  const itemContext = useAccordionItemContext();
60
- const forceMount = props.forceMount === true;
111
+ const asChild = props.asChild;
112
+ const forceMount = props.forceMount;
113
+ const transition = props.transition;
114
+ const children = props.children;
115
+ const restProps = getContentRestProps(props);
116
+
117
+ const shouldForceMount = forceMount === true;
61
118
 
62
- if (forceMount) {
119
+ if (shouldForceMount) {
63
120
  return (
64
121
  <AccordionContentImpl
65
- asChild={props.asChild}
122
+ {...restProps}
123
+ asChild={asChild}
66
124
  forceMount={true}
67
125
  present={itemContext.open}
68
- transition={props.transition}
126
+ transition={transition}
69
127
  >
70
- {props.children}
128
+ {children}
71
129
  </AccordionContentImpl>
72
130
  );
73
131
  }
@@ -77,12 +135,13 @@ export function AccordionContent(props: AccordionContentProps) {
77
135
  present={itemContext.open}
78
136
  render={(state) => (
79
137
  <AccordionContentImpl
80
- asChild={props.asChild}
138
+ {...restProps}
139
+ asChild={asChild}
81
140
  onExitComplete={state.onExitComplete}
82
141
  present={state.isPresent}
83
- transition={props.transition}
142
+ transition={transition}
84
143
  >
85
- {props.children}
144
+ {children}
86
145
  </AccordionContentImpl>
87
146
  )}
88
147
  />
@@ -40,9 +40,11 @@ export type AccordionTriggerProps = {
40
40
  children?: React.ReactElement;
41
41
  };
42
42
 
43
+ type AccordionContentGuiProps = React.Attributes & Record<string, unknown>;
44
+
43
45
  export type AccordionContentProps = {
44
46
  asChild?: boolean;
45
47
  forceMount?: boolean;
46
48
  transition?: PresenceMotionConfig;
47
49
  children?: React.ReactNode;
48
- };
50
+ } & AccordionContentGuiProps;