@velocis/dropdown1 0.2.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.
- package/LICENSE +21 -0
- package/dist/index.cjs +476 -0
- package/dist/index.d.cts +123 -0
- package/dist/index.d.ts +123 -0
- package/dist/index.js +439 -0
- package/package.json +49 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Velocis
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
"use strict";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/index.ts
|
|
22
|
+
var index_exports = {};
|
|
23
|
+
__export(index_exports, {
|
|
24
|
+
DROPDOWN1_DEFAULTS: () => DROPDOWN1_DEFAULTS,
|
|
25
|
+
DROPDOWN1_ITEM_DEFAULTS: () => DROPDOWN1_ITEM_DEFAULTS,
|
|
26
|
+
DROPDOWN1_SUBMENU_DEFAULTS: () => DROPDOWN1_SUBMENU_DEFAULTS,
|
|
27
|
+
Dropdown1: () => Dropdown1,
|
|
28
|
+
Dropdown1Context: () => Dropdown1Context,
|
|
29
|
+
Dropdown1Item: () => Dropdown1Item,
|
|
30
|
+
Dropdown1Root: () => Dropdown1Root,
|
|
31
|
+
Dropdown1SubMenu: () => Dropdown1SubMenu,
|
|
32
|
+
dropdown1ContentVariants: () => dropdown1ContentVariants,
|
|
33
|
+
dropdown1ItemVariants: () => dropdown1ItemVariants,
|
|
34
|
+
dropdown1Styles: () => dropdown1Styles,
|
|
35
|
+
dropdown1SubMenuContentVariants: () => dropdown1SubMenuContentVariants,
|
|
36
|
+
dropdown1SubMenuTriggerVariants: () => dropdown1SubMenuTriggerVariants,
|
|
37
|
+
dropdown1TriggerVariants: () => dropdown1TriggerVariants,
|
|
38
|
+
resolveDropdown1Styles: () => resolveDropdown1Styles,
|
|
39
|
+
useDropdown1: () => useDropdown1,
|
|
40
|
+
useDropdown1Context: () => useDropdown1Context
|
|
41
|
+
});
|
|
42
|
+
module.exports = __toCommonJS(index_exports);
|
|
43
|
+
|
|
44
|
+
// src/Dropdown1.tsx
|
|
45
|
+
var import_core3 = require("@velocis/core");
|
|
46
|
+
var import_react2 = require("react");
|
|
47
|
+
|
|
48
|
+
// src/Dropdown1.defaults.ts
|
|
49
|
+
var DROPDOWN1_DEFAULTS = {
|
|
50
|
+
contentWidth: "w-56",
|
|
51
|
+
fullWidth: false,
|
|
52
|
+
disabled: false,
|
|
53
|
+
closeOnScroll: true,
|
|
54
|
+
contentZIndex: "var(--velocis-z-dropdown)"
|
|
55
|
+
};
|
|
56
|
+
var DROPDOWN1_ITEM_DEFAULTS = {
|
|
57
|
+
closeOnSelect: true
|
|
58
|
+
};
|
|
59
|
+
var DROPDOWN1_SUBMENU_DEFAULTS = {
|
|
60
|
+
contentWidth: "w-48",
|
|
61
|
+
hoverDelayMs: 100
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
// src/Dropdown1.variants.ts
|
|
65
|
+
var import_class_variance_authority = require("class-variance-authority");
|
|
66
|
+
var dropdown1TriggerVariants = (0, import_class_variance_authority.cva)(
|
|
67
|
+
"flex items-center gap-2 rounded-velocis-md px-4 py-2 text-sm font-medium shadow-sm ring-1 ring-inset transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-velocis-primary/40",
|
|
68
|
+
{
|
|
69
|
+
variants: {
|
|
70
|
+
fullWidth: {
|
|
71
|
+
true: "w-full justify-between",
|
|
72
|
+
false: ""
|
|
73
|
+
},
|
|
74
|
+
disabled: {
|
|
75
|
+
true: "cursor-not-allowed opacity-60",
|
|
76
|
+
false: ""
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
defaultVariants: {
|
|
80
|
+
fullWidth: false,
|
|
81
|
+
disabled: false
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
);
|
|
85
|
+
var dropdown1ContentVariants = (0, import_class_variance_authority.cva)(
|
|
86
|
+
"fixed origin-top-right rounded-velocis-md focus:outline-none overflow-visible"
|
|
87
|
+
);
|
|
88
|
+
var dropdown1ItemVariants = (0, import_class_variance_authority.cva)(
|
|
89
|
+
"flex cursor-pointer items-center gap-2 px-4 py-2 text-sm transition-colors"
|
|
90
|
+
);
|
|
91
|
+
var dropdown1SubMenuTriggerVariants = (0, import_class_variance_authority.cva)(
|
|
92
|
+
"flex w-full cursor-default items-center justify-between px-4 py-2 text-sm transition-colors"
|
|
93
|
+
);
|
|
94
|
+
var dropdown1SubMenuContentVariants = (0, import_class_variance_authority.cva)(
|
|
95
|
+
"absolute top-0 right-full mr-2 w-48 rounded-velocis-md z-[10000]"
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
// src/context/Dropdown1Context.tsx
|
|
99
|
+
var import_react = require("react");
|
|
100
|
+
var Dropdown1Context = (0, import_react.createContext)(null);
|
|
101
|
+
function useDropdown1Context() {
|
|
102
|
+
return (0, import_react.useContext)(Dropdown1Context);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// src/icons/Dropdown1Icons.tsx
|
|
106
|
+
var import_core = require("@velocis/core");
|
|
107
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
108
|
+
function ChevronDownIcon({ className }) {
|
|
109
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core.Icon, { size: "sm", className, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M6 9l6 6 6-6", strokeLinecap: "round", strokeLinejoin: "round" }) }) });
|
|
110
|
+
}
|
|
111
|
+
function ChevronSubMenuIcon({ className, open }) {
|
|
112
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_core.Icon, { size: "sm", className: (0, import_core.cn)(className, open && "rotate-90"), children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M15 18l-6-6 6-6", strokeLinecap: "round", strokeLinejoin: "round" }) }) });
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// src/presets/dropdown1Styles.ts
|
|
116
|
+
var dropdown1Styles = {
|
|
117
|
+
trigger: "bg-velocis-background text-velocis-foreground ring-velocis-border hover:bg-velocis-border/30",
|
|
118
|
+
triggerIcon: "text-velocis-muted",
|
|
119
|
+
content: "bg-velocis-background text-velocis-foreground border border-velocis-border shadow-velocis-md ring-1 ring-velocis-border/40",
|
|
120
|
+
item: "text-velocis-foreground hover:bg-velocis-border/40 hover:text-velocis-foreground",
|
|
121
|
+
subMenuTrigger: "text-velocis-foreground hover:bg-velocis-border/40 hover:text-velocis-foreground",
|
|
122
|
+
subMenuContent: "bg-velocis-background text-velocis-foreground border border-velocis-border shadow-velocis-md",
|
|
123
|
+
subMenuIcon: "text-velocis-muted"
|
|
124
|
+
};
|
|
125
|
+
function resolveDropdown1Styles(overrides) {
|
|
126
|
+
const content = overrides?.content ?? dropdown1Styles.content;
|
|
127
|
+
return {
|
|
128
|
+
trigger: overrides?.trigger ?? dropdown1Styles.trigger,
|
|
129
|
+
triggerIcon: overrides?.triggerIcon ?? dropdown1Styles.triggerIcon,
|
|
130
|
+
content,
|
|
131
|
+
item: overrides?.item ?? dropdown1Styles.item,
|
|
132
|
+
subMenuTrigger: overrides?.subMenuTrigger ?? dropdown1Styles.subMenuTrigger,
|
|
133
|
+
subMenuContent: overrides?.subMenuContent ?? content,
|
|
134
|
+
subMenuIcon: overrides?.subMenuIcon ?? dropdown1Styles.subMenuIcon
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// src/positioning/computeDropdownStyle.ts
|
|
139
|
+
var import_core2 = require("@velocis/core");
|
|
140
|
+
function computeDropdownStyle({
|
|
141
|
+
anchorRect,
|
|
142
|
+
direction,
|
|
143
|
+
fullWidth,
|
|
144
|
+
contentWidthPx
|
|
145
|
+
}) {
|
|
146
|
+
const margin = 8;
|
|
147
|
+
const vw = window.innerWidth;
|
|
148
|
+
const rtl = (0, import_core2.isRTL)(direction);
|
|
149
|
+
const width = fullWidth ? anchorRect.width : contentWidthPx ?? Math.min(224, vw - margin * 2);
|
|
150
|
+
const top = anchorRect.bottom + 4;
|
|
151
|
+
const inlineStart = rtl ? anchorRect.right - width : anchorRect.left;
|
|
152
|
+
const left = Math.max(margin, Math.min(inlineStart, vw - width - margin));
|
|
153
|
+
return {
|
|
154
|
+
position: "fixed",
|
|
155
|
+
top,
|
|
156
|
+
left,
|
|
157
|
+
width: fullWidth ? anchorRect.width : width,
|
|
158
|
+
minWidth: fullWidth ? anchorRect.width : void 0
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
function parseContentWidthClass(contentWidth) {
|
|
162
|
+
const match = contentWidth.match(/^w-(\d+(?:\.\d+)?|\[\d+px\])$/);
|
|
163
|
+
if (!match?.[1]) return void 0;
|
|
164
|
+
const value = match[1];
|
|
165
|
+
if (value.startsWith("[")) {
|
|
166
|
+
return parseInt(value.slice(1, -2), 10);
|
|
167
|
+
}
|
|
168
|
+
const remMap = {
|
|
169
|
+
"48": 192,
|
|
170
|
+
"56": 224,
|
|
171
|
+
"64": 256,
|
|
172
|
+
"72": 288
|
|
173
|
+
};
|
|
174
|
+
return remMap[value];
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// src/Dropdown1.tsx
|
|
178
|
+
var import_jsx_runtime2 = require("react/jsx-runtime");
|
|
179
|
+
function useControllableOpen(controlledOpen, defaultOpen, onOpenChange) {
|
|
180
|
+
const [uncontrolledOpen, setUncontrolledOpen] = (0, import_react2.useState)(defaultOpen);
|
|
181
|
+
const isControlled = controlledOpen !== void 0;
|
|
182
|
+
const open = isControlled ? controlledOpen : uncontrolledOpen;
|
|
183
|
+
const setOpen = (0, import_react2.useCallback)(
|
|
184
|
+
(next) => {
|
|
185
|
+
if (!isControlled) {
|
|
186
|
+
setUncontrolledOpen(next);
|
|
187
|
+
}
|
|
188
|
+
onOpenChange?.(next);
|
|
189
|
+
},
|
|
190
|
+
[isControlled, onOpenChange]
|
|
191
|
+
);
|
|
192
|
+
return { open, setOpen };
|
|
193
|
+
}
|
|
194
|
+
function Dropdown1Root({
|
|
195
|
+
trigger,
|
|
196
|
+
children,
|
|
197
|
+
open: controlledOpen,
|
|
198
|
+
defaultOpen = false,
|
|
199
|
+
onOpenChange,
|
|
200
|
+
styles: stylesProp,
|
|
201
|
+
triggerClassName,
|
|
202
|
+
contentClassName,
|
|
203
|
+
contentWidth = DROPDOWN1_DEFAULTS.contentWidth,
|
|
204
|
+
maxHeight,
|
|
205
|
+
fullWidth = DROPDOWN1_DEFAULTS.fullWidth,
|
|
206
|
+
disabled = DROPDOWN1_DEFAULTS.disabled,
|
|
207
|
+
contentZIndex = DROPDOWN1_DEFAULTS.contentZIndex,
|
|
208
|
+
closeOnScroll = DROPDOWN1_DEFAULTS.closeOnScroll,
|
|
209
|
+
testId,
|
|
210
|
+
contentTestId
|
|
211
|
+
}) {
|
|
212
|
+
const direction = (0, import_core3.useDirection)();
|
|
213
|
+
const { open, setOpen } = useControllableOpen(controlledOpen, defaultOpen, onOpenChange);
|
|
214
|
+
const styles = resolveDropdown1Styles(stylesProp);
|
|
215
|
+
const dropdownRef = (0, import_react2.useRef)(null);
|
|
216
|
+
const buttonRef = (0, import_react2.useRef)(null);
|
|
217
|
+
const [positionStyle, setPositionStyle] = (0, import_react2.useState)({});
|
|
218
|
+
const closeDropdown = (0, import_react2.useCallback)(() => setOpen(false), [setOpen]);
|
|
219
|
+
const updatePosition = (0, import_react2.useCallback)(() => {
|
|
220
|
+
if (!buttonRef.current) return;
|
|
221
|
+
const rect = buttonRef.current.getBoundingClientRect();
|
|
222
|
+
const contentWidthPx = parseContentWidthClass(contentWidth);
|
|
223
|
+
setPositionStyle(
|
|
224
|
+
computeDropdownStyle({
|
|
225
|
+
anchorRect: rect,
|
|
226
|
+
direction,
|
|
227
|
+
fullWidth,
|
|
228
|
+
contentWidthPx
|
|
229
|
+
})
|
|
230
|
+
);
|
|
231
|
+
}, [contentWidth, direction, fullWidth]);
|
|
232
|
+
(0, import_react2.useEffect)(() => {
|
|
233
|
+
if (open) {
|
|
234
|
+
updatePosition();
|
|
235
|
+
}
|
|
236
|
+
}, [open, updatePosition]);
|
|
237
|
+
(0, import_react2.useEffect)(() => {
|
|
238
|
+
if (!open) return;
|
|
239
|
+
const handleClickOutside = (event) => {
|
|
240
|
+
if (dropdownRef.current && buttonRef.current && !dropdownRef.current.contains(event.target) && !buttonRef.current.contains(event.target)) {
|
|
241
|
+
setOpen(false);
|
|
242
|
+
}
|
|
243
|
+
};
|
|
244
|
+
const handleKeyDown = (event) => {
|
|
245
|
+
if (event.key === "Escape") {
|
|
246
|
+
setOpen(false);
|
|
247
|
+
}
|
|
248
|
+
};
|
|
249
|
+
const handleScroll = (event) => {
|
|
250
|
+
if (!closeOnScroll) return;
|
|
251
|
+
const target = event.target;
|
|
252
|
+
if (dropdownRef.current && target && !dropdownRef.current.contains(target) && !buttonRef.current?.contains(target)) {
|
|
253
|
+
setOpen(false);
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
257
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
258
|
+
document.addEventListener("scroll", handleScroll, true);
|
|
259
|
+
return () => {
|
|
260
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
261
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
262
|
+
document.removeEventListener("scroll", handleScroll, true);
|
|
263
|
+
};
|
|
264
|
+
}, [closeOnScroll, open, setOpen]);
|
|
265
|
+
const dropdownContent = open ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(Dropdown1Context.Provider, { value: { closeDropdown, styles }, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
266
|
+
"div",
|
|
267
|
+
{
|
|
268
|
+
ref: dropdownRef,
|
|
269
|
+
role: "menu",
|
|
270
|
+
"data-testid": contentTestId,
|
|
271
|
+
dir: direction,
|
|
272
|
+
className: (0, import_core3.cn)(
|
|
273
|
+
dropdown1ContentVariants(),
|
|
274
|
+
styles.content,
|
|
275
|
+
!fullWidth && contentWidth,
|
|
276
|
+
maxHeight && "overflow-y-auto",
|
|
277
|
+
contentClassName
|
|
278
|
+
),
|
|
279
|
+
style: {
|
|
280
|
+
...positionStyle,
|
|
281
|
+
zIndex: contentZIndex,
|
|
282
|
+
maxHeight: maxHeight || void 0
|
|
283
|
+
},
|
|
284
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "py-1", children })
|
|
285
|
+
}
|
|
286
|
+
) }) : null;
|
|
287
|
+
return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(import_jsx_runtime2.Fragment, { children: [
|
|
288
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
289
|
+
"div",
|
|
290
|
+
{
|
|
291
|
+
className: (0, import_core3.cn)(
|
|
292
|
+
"relative text-start",
|
|
293
|
+
fullWidth ? "block w-full" : "inline-block"
|
|
294
|
+
),
|
|
295
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
|
|
296
|
+
"button",
|
|
297
|
+
{
|
|
298
|
+
ref: buttonRef,
|
|
299
|
+
type: "button",
|
|
300
|
+
disabled,
|
|
301
|
+
"aria-expanded": open,
|
|
302
|
+
"aria-haspopup": "menu",
|
|
303
|
+
onClick: () => !disabled && setOpen(!open),
|
|
304
|
+
"data-testid": testId,
|
|
305
|
+
className: (0, import_core3.cn)(
|
|
306
|
+
dropdown1TriggerVariants({ fullWidth, disabled }),
|
|
307
|
+
styles.trigger,
|
|
308
|
+
triggerClassName
|
|
309
|
+
),
|
|
310
|
+
children: [
|
|
311
|
+
trigger,
|
|
312
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(ChevronDownIcon, { className: styles.triggerIcon })
|
|
313
|
+
]
|
|
314
|
+
}
|
|
315
|
+
)
|
|
316
|
+
}
|
|
317
|
+
),
|
|
318
|
+
open && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_core3.Portal, { children: dropdownContent })
|
|
319
|
+
] });
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
// src/components/Dropdown1Item.tsx
|
|
323
|
+
var import_core4 = require("@velocis/core");
|
|
324
|
+
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
325
|
+
function Dropdown1Item({
|
|
326
|
+
children,
|
|
327
|
+
onClick,
|
|
328
|
+
closeOnSelect = DROPDOWN1_ITEM_DEFAULTS.closeOnSelect,
|
|
329
|
+
styles: stylesProp,
|
|
330
|
+
className,
|
|
331
|
+
testId
|
|
332
|
+
}) {
|
|
333
|
+
const context = useDropdown1Context();
|
|
334
|
+
const itemStyles = stylesProp?.item ?? context?.styles.item;
|
|
335
|
+
const handleClick = () => {
|
|
336
|
+
onClick?.();
|
|
337
|
+
if (closeOnSelect && context?.closeDropdown) {
|
|
338
|
+
context.closeDropdown();
|
|
339
|
+
}
|
|
340
|
+
};
|
|
341
|
+
return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
342
|
+
"div",
|
|
343
|
+
{
|
|
344
|
+
role: "menuitem",
|
|
345
|
+
tabIndex: 0,
|
|
346
|
+
onClick: handleClick,
|
|
347
|
+
onKeyDown: (e) => {
|
|
348
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
349
|
+
e.preventDefault();
|
|
350
|
+
handleClick();
|
|
351
|
+
}
|
|
352
|
+
},
|
|
353
|
+
"data-testid": testId,
|
|
354
|
+
className: (0, import_core4.cn)(dropdown1ItemVariants(), itemStyles, className),
|
|
355
|
+
children
|
|
356
|
+
}
|
|
357
|
+
);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// src/components/Dropdown1SubMenu.tsx
|
|
361
|
+
var import_core5 = require("@velocis/core");
|
|
362
|
+
var import_react3 = require("react");
|
|
363
|
+
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
364
|
+
function Dropdown1SubMenu({
|
|
365
|
+
trigger,
|
|
366
|
+
children,
|
|
367
|
+
contentWidth = DROPDOWN1_SUBMENU_DEFAULTS.contentWidth,
|
|
368
|
+
styles: stylesProp,
|
|
369
|
+
className
|
|
370
|
+
}) {
|
|
371
|
+
const context = useDropdown1Context();
|
|
372
|
+
const subMenuTriggerStyles = stylesProp?.subMenuTrigger ?? context?.styles.subMenuTrigger;
|
|
373
|
+
const subMenuContentStyles = stylesProp?.subMenuContent ?? context?.styles.subMenuContent;
|
|
374
|
+
const subMenuIconStyles = stylesProp?.subMenuIcon ?? context?.styles.subMenuIcon;
|
|
375
|
+
const [isOpen, setIsOpen] = (0, import_react3.useState)(false);
|
|
376
|
+
const timeoutRef = (0, import_react3.useRef)(null);
|
|
377
|
+
const containerRef = (0, import_react3.useRef)(null);
|
|
378
|
+
const handleMouseEnter = () => {
|
|
379
|
+
if (timeoutRef.current) {
|
|
380
|
+
clearTimeout(timeoutRef.current);
|
|
381
|
+
timeoutRef.current = null;
|
|
382
|
+
}
|
|
383
|
+
setIsOpen(true);
|
|
384
|
+
};
|
|
385
|
+
const handleMouseLeave = () => {
|
|
386
|
+
timeoutRef.current = setTimeout(() => {
|
|
387
|
+
setIsOpen(false);
|
|
388
|
+
}, DROPDOWN1_SUBMENU_DEFAULTS.hoverDelayMs);
|
|
389
|
+
};
|
|
390
|
+
(0, import_react3.useEffect)(() => {
|
|
391
|
+
return () => {
|
|
392
|
+
if (timeoutRef.current) {
|
|
393
|
+
clearTimeout(timeoutRef.current);
|
|
394
|
+
}
|
|
395
|
+
};
|
|
396
|
+
}, []);
|
|
397
|
+
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
398
|
+
"div",
|
|
399
|
+
{
|
|
400
|
+
ref: containerRef,
|
|
401
|
+
className: "relative w-full",
|
|
402
|
+
onMouseEnter: handleMouseEnter,
|
|
403
|
+
onMouseLeave: handleMouseLeave,
|
|
404
|
+
children: [
|
|
405
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
406
|
+
"div",
|
|
407
|
+
{
|
|
408
|
+
role: "menuitem",
|
|
409
|
+
"aria-haspopup": "menu",
|
|
410
|
+
"aria-expanded": isOpen,
|
|
411
|
+
className: (0, import_core5.cn)(dropdown1SubMenuTriggerVariants(), subMenuTriggerStyles),
|
|
412
|
+
children: [
|
|
413
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "flex items-center gap-2", children: trigger }),
|
|
414
|
+
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(ChevronSubMenuIcon, { open: isOpen, className: (0, import_core5.cn)("transition-transform", subMenuIconStyles) })
|
|
415
|
+
]
|
|
416
|
+
}
|
|
417
|
+
),
|
|
418
|
+
isOpen && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
419
|
+
"div",
|
|
420
|
+
{
|
|
421
|
+
role: "menu",
|
|
422
|
+
className: (0, import_core5.cn)(
|
|
423
|
+
dropdown1SubMenuContentVariants(),
|
|
424
|
+
subMenuContentStyles,
|
|
425
|
+
contentWidth !== "w-48" && contentWidth,
|
|
426
|
+
className
|
|
427
|
+
),
|
|
428
|
+
onMouseEnter: handleMouseEnter,
|
|
429
|
+
onMouseLeave: handleMouseLeave,
|
|
430
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "py-1", children })
|
|
431
|
+
}
|
|
432
|
+
)
|
|
433
|
+
]
|
|
434
|
+
}
|
|
435
|
+
);
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// src/hooks/useDropdown1.ts
|
|
439
|
+
var import_react4 = require("react");
|
|
440
|
+
function useDropdown1(options = {}) {
|
|
441
|
+
const [open, setOpen] = (0, import_react4.useState)(options.defaultOpen ?? false);
|
|
442
|
+
const onOpenChange = (0, import_react4.useCallback)((next) => {
|
|
443
|
+
setOpen(next);
|
|
444
|
+
}, []);
|
|
445
|
+
return {
|
|
446
|
+
open,
|
|
447
|
+
setOpen,
|
|
448
|
+
dropdownProps: { open, onOpenChange }
|
|
449
|
+
};
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// src/index.ts
|
|
453
|
+
var Dropdown1 = Object.assign(Dropdown1Root, {
|
|
454
|
+
Item: Dropdown1Item,
|
|
455
|
+
SubMenu: Dropdown1SubMenu
|
|
456
|
+
});
|
|
457
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
458
|
+
0 && (module.exports = {
|
|
459
|
+
DROPDOWN1_DEFAULTS,
|
|
460
|
+
DROPDOWN1_ITEM_DEFAULTS,
|
|
461
|
+
DROPDOWN1_SUBMENU_DEFAULTS,
|
|
462
|
+
Dropdown1,
|
|
463
|
+
Dropdown1Context,
|
|
464
|
+
Dropdown1Item,
|
|
465
|
+
Dropdown1Root,
|
|
466
|
+
Dropdown1SubMenu,
|
|
467
|
+
dropdown1ContentVariants,
|
|
468
|
+
dropdown1ItemVariants,
|
|
469
|
+
dropdown1Styles,
|
|
470
|
+
dropdown1SubMenuContentVariants,
|
|
471
|
+
dropdown1SubMenuTriggerVariants,
|
|
472
|
+
dropdown1TriggerVariants,
|
|
473
|
+
resolveDropdown1Styles,
|
|
474
|
+
useDropdown1,
|
|
475
|
+
useDropdown1Context
|
|
476
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
4
|
+
|
|
5
|
+
type Dropdown1Styles = {
|
|
6
|
+
/** Trigger button — bg + text + border/hover as one coordinated set */
|
|
7
|
+
trigger?: string;
|
|
8
|
+
/** Chevron on trigger */
|
|
9
|
+
triggerIcon?: string;
|
|
10
|
+
/** Main menu panel — bg + text + border/shadow */
|
|
11
|
+
content?: string;
|
|
12
|
+
/** Menu item — text + hover bg/text */
|
|
13
|
+
item?: string;
|
|
14
|
+
/** Sub-menu row — text + hover bg/text */
|
|
15
|
+
subMenuTrigger?: string;
|
|
16
|
+
/** Sub-menu panel — defaults to `content` when omitted */
|
|
17
|
+
subMenuContent?: string;
|
|
18
|
+
/** Chevron on sub-menu row */
|
|
19
|
+
subMenuIcon?: string;
|
|
20
|
+
};
|
|
21
|
+
declare const dropdown1Styles: {
|
|
22
|
+
readonly trigger: "bg-velocis-background text-velocis-foreground ring-velocis-border hover:bg-velocis-border/30";
|
|
23
|
+
readonly triggerIcon: "text-velocis-muted";
|
|
24
|
+
readonly content: "bg-velocis-background text-velocis-foreground border border-velocis-border shadow-velocis-md ring-1 ring-velocis-border/40";
|
|
25
|
+
readonly item: "text-velocis-foreground hover:bg-velocis-border/40 hover:text-velocis-foreground";
|
|
26
|
+
readonly subMenuTrigger: "text-velocis-foreground hover:bg-velocis-border/40 hover:text-velocis-foreground";
|
|
27
|
+
readonly subMenuContent: "bg-velocis-background text-velocis-foreground border border-velocis-border shadow-velocis-md";
|
|
28
|
+
readonly subMenuIcon: "text-velocis-muted";
|
|
29
|
+
};
|
|
30
|
+
type ResolvedDropdown1Styles = Required<Dropdown1Styles>;
|
|
31
|
+
declare function resolveDropdown1Styles(overrides?: Partial<Dropdown1Styles>): ResolvedDropdown1Styles;
|
|
32
|
+
|
|
33
|
+
type Dropdown1Props = {
|
|
34
|
+
trigger: ReactNode;
|
|
35
|
+
children: ReactNode;
|
|
36
|
+
open?: boolean;
|
|
37
|
+
defaultOpen?: boolean;
|
|
38
|
+
onOpenChange?: (open: boolean) => void;
|
|
39
|
+
/** Override coordinated bg/text/hover classes per layer */
|
|
40
|
+
styles?: Partial<Dropdown1Styles>;
|
|
41
|
+
triggerClassName?: string;
|
|
42
|
+
contentClassName?: string;
|
|
43
|
+
contentWidth?: string;
|
|
44
|
+
maxHeight?: string;
|
|
45
|
+
fullWidth?: boolean;
|
|
46
|
+
disabled?: boolean;
|
|
47
|
+
contentZIndex?: number | string;
|
|
48
|
+
closeOnScroll?: boolean;
|
|
49
|
+
testId?: string;
|
|
50
|
+
contentTestId?: string;
|
|
51
|
+
};
|
|
52
|
+
type Dropdown1ItemProps = {
|
|
53
|
+
children: ReactNode;
|
|
54
|
+
onClick?: () => void;
|
|
55
|
+
closeOnSelect?: boolean;
|
|
56
|
+
/** Override item text/hover colors (defaults to root `styles.item`) */
|
|
57
|
+
styles?: Pick<Dropdown1Styles, 'item'>;
|
|
58
|
+
className?: string;
|
|
59
|
+
testId?: string;
|
|
60
|
+
};
|
|
61
|
+
type Dropdown1SubMenuProps = {
|
|
62
|
+
trigger: ReactNode;
|
|
63
|
+
children: ReactNode;
|
|
64
|
+
contentWidth?: string;
|
|
65
|
+
/** Override sub-menu colors (defaults to root styles) */
|
|
66
|
+
styles?: Pick<Dropdown1Styles, 'subMenuTrigger' | 'subMenuContent' | 'subMenuIcon'>;
|
|
67
|
+
className?: string;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
declare function Dropdown1Root({ trigger, children, open: controlledOpen, defaultOpen, onOpenChange, styles: stylesProp, triggerClassName, contentClassName, contentWidth, maxHeight, fullWidth, disabled, contentZIndex, closeOnScroll, testId, contentTestId, }: Dropdown1Props): react.JSX.Element;
|
|
71
|
+
|
|
72
|
+
declare function Dropdown1Item({ children, onClick, closeOnSelect, styles: stylesProp, className, testId, }: Dropdown1ItemProps): react.JSX.Element;
|
|
73
|
+
|
|
74
|
+
declare function Dropdown1SubMenu({ trigger, children, contentWidth, styles: stylesProp, className, }: Dropdown1SubMenuProps): react.JSX.Element;
|
|
75
|
+
|
|
76
|
+
type UseDropdown1Options = {
|
|
77
|
+
defaultOpen?: boolean;
|
|
78
|
+
};
|
|
79
|
+
type UseDropdown1Result = {
|
|
80
|
+
open: boolean;
|
|
81
|
+
setOpen: (open: boolean) => void;
|
|
82
|
+
dropdownProps: Pick<Dropdown1Props, 'open' | 'onOpenChange'>;
|
|
83
|
+
};
|
|
84
|
+
declare function useDropdown1(options?: UseDropdown1Options): UseDropdown1Result;
|
|
85
|
+
|
|
86
|
+
type Dropdown1ContextValue = {
|
|
87
|
+
closeDropdown: () => void;
|
|
88
|
+
styles: ResolvedDropdown1Styles;
|
|
89
|
+
};
|
|
90
|
+
declare const Dropdown1Context: react.Context<Dropdown1ContextValue | null>;
|
|
91
|
+
declare function useDropdown1Context(): Dropdown1ContextValue | null;
|
|
92
|
+
|
|
93
|
+
declare const DROPDOWN1_DEFAULTS: {
|
|
94
|
+
readonly contentWidth: "w-56";
|
|
95
|
+
readonly fullWidth: false;
|
|
96
|
+
readonly disabled: false;
|
|
97
|
+
readonly closeOnScroll: true;
|
|
98
|
+
readonly contentZIndex: "var(--velocis-z-dropdown)";
|
|
99
|
+
};
|
|
100
|
+
declare const DROPDOWN1_ITEM_DEFAULTS: {
|
|
101
|
+
readonly closeOnSelect: true;
|
|
102
|
+
};
|
|
103
|
+
declare const DROPDOWN1_SUBMENU_DEFAULTS: {
|
|
104
|
+
readonly contentWidth: "w-48";
|
|
105
|
+
readonly hoverDelayMs: 100;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/** Layout/structure only — colors come from `dropdown1Styles` + `styles` prop */
|
|
109
|
+
declare const dropdown1TriggerVariants: (props?: ({
|
|
110
|
+
fullWidth?: boolean | null | undefined;
|
|
111
|
+
disabled?: boolean | null | undefined;
|
|
112
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
113
|
+
declare const dropdown1ContentVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
|
|
114
|
+
declare const dropdown1ItemVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
|
|
115
|
+
declare const dropdown1SubMenuTriggerVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
|
|
116
|
+
declare const dropdown1SubMenuContentVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
|
|
117
|
+
|
|
118
|
+
declare const Dropdown1: typeof Dropdown1Root & {
|
|
119
|
+
Item: typeof Dropdown1Item;
|
|
120
|
+
SubMenu: typeof Dropdown1SubMenu;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export { DROPDOWN1_DEFAULTS, DROPDOWN1_ITEM_DEFAULTS, DROPDOWN1_SUBMENU_DEFAULTS, Dropdown1, Dropdown1Context, type Dropdown1ContextValue, Dropdown1Item, type Dropdown1ItemProps, type Dropdown1Props, Dropdown1Root, type Dropdown1Styles, Dropdown1SubMenu, type Dropdown1SubMenuProps, type ResolvedDropdown1Styles, type UseDropdown1Options, type UseDropdown1Result, dropdown1ContentVariants, dropdown1ItemVariants, dropdown1Styles, dropdown1SubMenuContentVariants, dropdown1SubMenuTriggerVariants, dropdown1TriggerVariants, resolveDropdown1Styles, useDropdown1, useDropdown1Context };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import * as class_variance_authority_types from 'class-variance-authority/types';
|
|
4
|
+
|
|
5
|
+
type Dropdown1Styles = {
|
|
6
|
+
/** Trigger button — bg + text + border/hover as one coordinated set */
|
|
7
|
+
trigger?: string;
|
|
8
|
+
/** Chevron on trigger */
|
|
9
|
+
triggerIcon?: string;
|
|
10
|
+
/** Main menu panel — bg + text + border/shadow */
|
|
11
|
+
content?: string;
|
|
12
|
+
/** Menu item — text + hover bg/text */
|
|
13
|
+
item?: string;
|
|
14
|
+
/** Sub-menu row — text + hover bg/text */
|
|
15
|
+
subMenuTrigger?: string;
|
|
16
|
+
/** Sub-menu panel — defaults to `content` when omitted */
|
|
17
|
+
subMenuContent?: string;
|
|
18
|
+
/** Chevron on sub-menu row */
|
|
19
|
+
subMenuIcon?: string;
|
|
20
|
+
};
|
|
21
|
+
declare const dropdown1Styles: {
|
|
22
|
+
readonly trigger: "bg-velocis-background text-velocis-foreground ring-velocis-border hover:bg-velocis-border/30";
|
|
23
|
+
readonly triggerIcon: "text-velocis-muted";
|
|
24
|
+
readonly content: "bg-velocis-background text-velocis-foreground border border-velocis-border shadow-velocis-md ring-1 ring-velocis-border/40";
|
|
25
|
+
readonly item: "text-velocis-foreground hover:bg-velocis-border/40 hover:text-velocis-foreground";
|
|
26
|
+
readonly subMenuTrigger: "text-velocis-foreground hover:bg-velocis-border/40 hover:text-velocis-foreground";
|
|
27
|
+
readonly subMenuContent: "bg-velocis-background text-velocis-foreground border border-velocis-border shadow-velocis-md";
|
|
28
|
+
readonly subMenuIcon: "text-velocis-muted";
|
|
29
|
+
};
|
|
30
|
+
type ResolvedDropdown1Styles = Required<Dropdown1Styles>;
|
|
31
|
+
declare function resolveDropdown1Styles(overrides?: Partial<Dropdown1Styles>): ResolvedDropdown1Styles;
|
|
32
|
+
|
|
33
|
+
type Dropdown1Props = {
|
|
34
|
+
trigger: ReactNode;
|
|
35
|
+
children: ReactNode;
|
|
36
|
+
open?: boolean;
|
|
37
|
+
defaultOpen?: boolean;
|
|
38
|
+
onOpenChange?: (open: boolean) => void;
|
|
39
|
+
/** Override coordinated bg/text/hover classes per layer */
|
|
40
|
+
styles?: Partial<Dropdown1Styles>;
|
|
41
|
+
triggerClassName?: string;
|
|
42
|
+
contentClassName?: string;
|
|
43
|
+
contentWidth?: string;
|
|
44
|
+
maxHeight?: string;
|
|
45
|
+
fullWidth?: boolean;
|
|
46
|
+
disabled?: boolean;
|
|
47
|
+
contentZIndex?: number | string;
|
|
48
|
+
closeOnScroll?: boolean;
|
|
49
|
+
testId?: string;
|
|
50
|
+
contentTestId?: string;
|
|
51
|
+
};
|
|
52
|
+
type Dropdown1ItemProps = {
|
|
53
|
+
children: ReactNode;
|
|
54
|
+
onClick?: () => void;
|
|
55
|
+
closeOnSelect?: boolean;
|
|
56
|
+
/** Override item text/hover colors (defaults to root `styles.item`) */
|
|
57
|
+
styles?: Pick<Dropdown1Styles, 'item'>;
|
|
58
|
+
className?: string;
|
|
59
|
+
testId?: string;
|
|
60
|
+
};
|
|
61
|
+
type Dropdown1SubMenuProps = {
|
|
62
|
+
trigger: ReactNode;
|
|
63
|
+
children: ReactNode;
|
|
64
|
+
contentWidth?: string;
|
|
65
|
+
/** Override sub-menu colors (defaults to root styles) */
|
|
66
|
+
styles?: Pick<Dropdown1Styles, 'subMenuTrigger' | 'subMenuContent' | 'subMenuIcon'>;
|
|
67
|
+
className?: string;
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
declare function Dropdown1Root({ trigger, children, open: controlledOpen, defaultOpen, onOpenChange, styles: stylesProp, triggerClassName, contentClassName, contentWidth, maxHeight, fullWidth, disabled, contentZIndex, closeOnScroll, testId, contentTestId, }: Dropdown1Props): react.JSX.Element;
|
|
71
|
+
|
|
72
|
+
declare function Dropdown1Item({ children, onClick, closeOnSelect, styles: stylesProp, className, testId, }: Dropdown1ItemProps): react.JSX.Element;
|
|
73
|
+
|
|
74
|
+
declare function Dropdown1SubMenu({ trigger, children, contentWidth, styles: stylesProp, className, }: Dropdown1SubMenuProps): react.JSX.Element;
|
|
75
|
+
|
|
76
|
+
type UseDropdown1Options = {
|
|
77
|
+
defaultOpen?: boolean;
|
|
78
|
+
};
|
|
79
|
+
type UseDropdown1Result = {
|
|
80
|
+
open: boolean;
|
|
81
|
+
setOpen: (open: boolean) => void;
|
|
82
|
+
dropdownProps: Pick<Dropdown1Props, 'open' | 'onOpenChange'>;
|
|
83
|
+
};
|
|
84
|
+
declare function useDropdown1(options?: UseDropdown1Options): UseDropdown1Result;
|
|
85
|
+
|
|
86
|
+
type Dropdown1ContextValue = {
|
|
87
|
+
closeDropdown: () => void;
|
|
88
|
+
styles: ResolvedDropdown1Styles;
|
|
89
|
+
};
|
|
90
|
+
declare const Dropdown1Context: react.Context<Dropdown1ContextValue | null>;
|
|
91
|
+
declare function useDropdown1Context(): Dropdown1ContextValue | null;
|
|
92
|
+
|
|
93
|
+
declare const DROPDOWN1_DEFAULTS: {
|
|
94
|
+
readonly contentWidth: "w-56";
|
|
95
|
+
readonly fullWidth: false;
|
|
96
|
+
readonly disabled: false;
|
|
97
|
+
readonly closeOnScroll: true;
|
|
98
|
+
readonly contentZIndex: "var(--velocis-z-dropdown)";
|
|
99
|
+
};
|
|
100
|
+
declare const DROPDOWN1_ITEM_DEFAULTS: {
|
|
101
|
+
readonly closeOnSelect: true;
|
|
102
|
+
};
|
|
103
|
+
declare const DROPDOWN1_SUBMENU_DEFAULTS: {
|
|
104
|
+
readonly contentWidth: "w-48";
|
|
105
|
+
readonly hoverDelayMs: 100;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/** Layout/structure only — colors come from `dropdown1Styles` + `styles` prop */
|
|
109
|
+
declare const dropdown1TriggerVariants: (props?: ({
|
|
110
|
+
fullWidth?: boolean | null | undefined;
|
|
111
|
+
disabled?: boolean | null | undefined;
|
|
112
|
+
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
113
|
+
declare const dropdown1ContentVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
|
|
114
|
+
declare const dropdown1ItemVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
|
|
115
|
+
declare const dropdown1SubMenuTriggerVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
|
|
116
|
+
declare const dropdown1SubMenuContentVariants: (props?: class_variance_authority_types.ClassProp | undefined) => string;
|
|
117
|
+
|
|
118
|
+
declare const Dropdown1: typeof Dropdown1Root & {
|
|
119
|
+
Item: typeof Dropdown1Item;
|
|
120
|
+
SubMenu: typeof Dropdown1SubMenu;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
export { DROPDOWN1_DEFAULTS, DROPDOWN1_ITEM_DEFAULTS, DROPDOWN1_SUBMENU_DEFAULTS, Dropdown1, Dropdown1Context, type Dropdown1ContextValue, Dropdown1Item, type Dropdown1ItemProps, type Dropdown1Props, Dropdown1Root, type Dropdown1Styles, Dropdown1SubMenu, type Dropdown1SubMenuProps, type ResolvedDropdown1Styles, type UseDropdown1Options, type UseDropdown1Result, dropdown1ContentVariants, dropdown1ItemVariants, dropdown1Styles, dropdown1SubMenuContentVariants, dropdown1SubMenuTriggerVariants, dropdown1TriggerVariants, resolveDropdown1Styles, useDropdown1, useDropdown1Context };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
// src/Dropdown1.tsx
|
|
4
|
+
import { cn as cn2, Portal, useDirection } from "@velocis/core";
|
|
5
|
+
import {
|
|
6
|
+
useCallback,
|
|
7
|
+
useEffect,
|
|
8
|
+
useRef,
|
|
9
|
+
useState
|
|
10
|
+
} from "react";
|
|
11
|
+
|
|
12
|
+
// src/Dropdown1.defaults.ts
|
|
13
|
+
var DROPDOWN1_DEFAULTS = {
|
|
14
|
+
contentWidth: "w-56",
|
|
15
|
+
fullWidth: false,
|
|
16
|
+
disabled: false,
|
|
17
|
+
closeOnScroll: true,
|
|
18
|
+
contentZIndex: "var(--velocis-z-dropdown)"
|
|
19
|
+
};
|
|
20
|
+
var DROPDOWN1_ITEM_DEFAULTS = {
|
|
21
|
+
closeOnSelect: true
|
|
22
|
+
};
|
|
23
|
+
var DROPDOWN1_SUBMENU_DEFAULTS = {
|
|
24
|
+
contentWidth: "w-48",
|
|
25
|
+
hoverDelayMs: 100
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// src/Dropdown1.variants.ts
|
|
29
|
+
import { cva } from "class-variance-authority";
|
|
30
|
+
var dropdown1TriggerVariants = cva(
|
|
31
|
+
"flex items-center gap-2 rounded-velocis-md px-4 py-2 text-sm font-medium shadow-sm ring-1 ring-inset transition-colors focus:outline-none focus-visible:ring-2 focus-visible:ring-velocis-primary/40",
|
|
32
|
+
{
|
|
33
|
+
variants: {
|
|
34
|
+
fullWidth: {
|
|
35
|
+
true: "w-full justify-between",
|
|
36
|
+
false: ""
|
|
37
|
+
},
|
|
38
|
+
disabled: {
|
|
39
|
+
true: "cursor-not-allowed opacity-60",
|
|
40
|
+
false: ""
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
defaultVariants: {
|
|
44
|
+
fullWidth: false,
|
|
45
|
+
disabled: false
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
);
|
|
49
|
+
var dropdown1ContentVariants = cva(
|
|
50
|
+
"fixed origin-top-right rounded-velocis-md focus:outline-none overflow-visible"
|
|
51
|
+
);
|
|
52
|
+
var dropdown1ItemVariants = cva(
|
|
53
|
+
"flex cursor-pointer items-center gap-2 px-4 py-2 text-sm transition-colors"
|
|
54
|
+
);
|
|
55
|
+
var dropdown1SubMenuTriggerVariants = cva(
|
|
56
|
+
"flex w-full cursor-default items-center justify-between px-4 py-2 text-sm transition-colors"
|
|
57
|
+
);
|
|
58
|
+
var dropdown1SubMenuContentVariants = cva(
|
|
59
|
+
"absolute top-0 right-full mr-2 w-48 rounded-velocis-md z-[10000]"
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
// src/context/Dropdown1Context.tsx
|
|
63
|
+
import { createContext, useContext } from "react";
|
|
64
|
+
var Dropdown1Context = createContext(null);
|
|
65
|
+
function useDropdown1Context() {
|
|
66
|
+
return useContext(Dropdown1Context);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// src/icons/Dropdown1Icons.tsx
|
|
70
|
+
import { cn, Icon } from "@velocis/core";
|
|
71
|
+
import { jsx } from "react/jsx-runtime";
|
|
72
|
+
function ChevronDownIcon({ className }) {
|
|
73
|
+
return /* @__PURE__ */ jsx(Icon, { size: "sm", className, children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M6 9l6 6 6-6", strokeLinecap: "round", strokeLinejoin: "round" }) }) });
|
|
74
|
+
}
|
|
75
|
+
function ChevronSubMenuIcon({ className, open }) {
|
|
76
|
+
return /* @__PURE__ */ jsx(Icon, { size: "sm", className: cn(className, open && "rotate-90"), children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": "true", children: /* @__PURE__ */ jsx("path", { d: "M15 18l-6-6 6-6", strokeLinecap: "round", strokeLinejoin: "round" }) }) });
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// src/presets/dropdown1Styles.ts
|
|
80
|
+
var dropdown1Styles = {
|
|
81
|
+
trigger: "bg-velocis-background text-velocis-foreground ring-velocis-border hover:bg-velocis-border/30",
|
|
82
|
+
triggerIcon: "text-velocis-muted",
|
|
83
|
+
content: "bg-velocis-background text-velocis-foreground border border-velocis-border shadow-velocis-md ring-1 ring-velocis-border/40",
|
|
84
|
+
item: "text-velocis-foreground hover:bg-velocis-border/40 hover:text-velocis-foreground",
|
|
85
|
+
subMenuTrigger: "text-velocis-foreground hover:bg-velocis-border/40 hover:text-velocis-foreground",
|
|
86
|
+
subMenuContent: "bg-velocis-background text-velocis-foreground border border-velocis-border shadow-velocis-md",
|
|
87
|
+
subMenuIcon: "text-velocis-muted"
|
|
88
|
+
};
|
|
89
|
+
function resolveDropdown1Styles(overrides) {
|
|
90
|
+
const content = overrides?.content ?? dropdown1Styles.content;
|
|
91
|
+
return {
|
|
92
|
+
trigger: overrides?.trigger ?? dropdown1Styles.trigger,
|
|
93
|
+
triggerIcon: overrides?.triggerIcon ?? dropdown1Styles.triggerIcon,
|
|
94
|
+
content,
|
|
95
|
+
item: overrides?.item ?? dropdown1Styles.item,
|
|
96
|
+
subMenuTrigger: overrides?.subMenuTrigger ?? dropdown1Styles.subMenuTrigger,
|
|
97
|
+
subMenuContent: overrides?.subMenuContent ?? content,
|
|
98
|
+
subMenuIcon: overrides?.subMenuIcon ?? dropdown1Styles.subMenuIcon
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// src/positioning/computeDropdownStyle.ts
|
|
103
|
+
import { isRTL } from "@velocis/core";
|
|
104
|
+
function computeDropdownStyle({
|
|
105
|
+
anchorRect,
|
|
106
|
+
direction,
|
|
107
|
+
fullWidth,
|
|
108
|
+
contentWidthPx
|
|
109
|
+
}) {
|
|
110
|
+
const margin = 8;
|
|
111
|
+
const vw = window.innerWidth;
|
|
112
|
+
const rtl = isRTL(direction);
|
|
113
|
+
const width = fullWidth ? anchorRect.width : contentWidthPx ?? Math.min(224, vw - margin * 2);
|
|
114
|
+
const top = anchorRect.bottom + 4;
|
|
115
|
+
const inlineStart = rtl ? anchorRect.right - width : anchorRect.left;
|
|
116
|
+
const left = Math.max(margin, Math.min(inlineStart, vw - width - margin));
|
|
117
|
+
return {
|
|
118
|
+
position: "fixed",
|
|
119
|
+
top,
|
|
120
|
+
left,
|
|
121
|
+
width: fullWidth ? anchorRect.width : width,
|
|
122
|
+
minWidth: fullWidth ? anchorRect.width : void 0
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
function parseContentWidthClass(contentWidth) {
|
|
126
|
+
const match = contentWidth.match(/^w-(\d+(?:\.\d+)?|\[\d+px\])$/);
|
|
127
|
+
if (!match?.[1]) return void 0;
|
|
128
|
+
const value = match[1];
|
|
129
|
+
if (value.startsWith("[")) {
|
|
130
|
+
return parseInt(value.slice(1, -2), 10);
|
|
131
|
+
}
|
|
132
|
+
const remMap = {
|
|
133
|
+
"48": 192,
|
|
134
|
+
"56": 224,
|
|
135
|
+
"64": 256,
|
|
136
|
+
"72": 288
|
|
137
|
+
};
|
|
138
|
+
return remMap[value];
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// src/Dropdown1.tsx
|
|
142
|
+
import { Fragment, jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
143
|
+
function useControllableOpen(controlledOpen, defaultOpen, onOpenChange) {
|
|
144
|
+
const [uncontrolledOpen, setUncontrolledOpen] = useState(defaultOpen);
|
|
145
|
+
const isControlled = controlledOpen !== void 0;
|
|
146
|
+
const open = isControlled ? controlledOpen : uncontrolledOpen;
|
|
147
|
+
const setOpen = useCallback(
|
|
148
|
+
(next) => {
|
|
149
|
+
if (!isControlled) {
|
|
150
|
+
setUncontrolledOpen(next);
|
|
151
|
+
}
|
|
152
|
+
onOpenChange?.(next);
|
|
153
|
+
},
|
|
154
|
+
[isControlled, onOpenChange]
|
|
155
|
+
);
|
|
156
|
+
return { open, setOpen };
|
|
157
|
+
}
|
|
158
|
+
function Dropdown1Root({
|
|
159
|
+
trigger,
|
|
160
|
+
children,
|
|
161
|
+
open: controlledOpen,
|
|
162
|
+
defaultOpen = false,
|
|
163
|
+
onOpenChange,
|
|
164
|
+
styles: stylesProp,
|
|
165
|
+
triggerClassName,
|
|
166
|
+
contentClassName,
|
|
167
|
+
contentWidth = DROPDOWN1_DEFAULTS.contentWidth,
|
|
168
|
+
maxHeight,
|
|
169
|
+
fullWidth = DROPDOWN1_DEFAULTS.fullWidth,
|
|
170
|
+
disabled = DROPDOWN1_DEFAULTS.disabled,
|
|
171
|
+
contentZIndex = DROPDOWN1_DEFAULTS.contentZIndex,
|
|
172
|
+
closeOnScroll = DROPDOWN1_DEFAULTS.closeOnScroll,
|
|
173
|
+
testId,
|
|
174
|
+
contentTestId
|
|
175
|
+
}) {
|
|
176
|
+
const direction = useDirection();
|
|
177
|
+
const { open, setOpen } = useControllableOpen(controlledOpen, defaultOpen, onOpenChange);
|
|
178
|
+
const styles = resolveDropdown1Styles(stylesProp);
|
|
179
|
+
const dropdownRef = useRef(null);
|
|
180
|
+
const buttonRef = useRef(null);
|
|
181
|
+
const [positionStyle, setPositionStyle] = useState({});
|
|
182
|
+
const closeDropdown = useCallback(() => setOpen(false), [setOpen]);
|
|
183
|
+
const updatePosition = useCallback(() => {
|
|
184
|
+
if (!buttonRef.current) return;
|
|
185
|
+
const rect = buttonRef.current.getBoundingClientRect();
|
|
186
|
+
const contentWidthPx = parseContentWidthClass(contentWidth);
|
|
187
|
+
setPositionStyle(
|
|
188
|
+
computeDropdownStyle({
|
|
189
|
+
anchorRect: rect,
|
|
190
|
+
direction,
|
|
191
|
+
fullWidth,
|
|
192
|
+
contentWidthPx
|
|
193
|
+
})
|
|
194
|
+
);
|
|
195
|
+
}, [contentWidth, direction, fullWidth]);
|
|
196
|
+
useEffect(() => {
|
|
197
|
+
if (open) {
|
|
198
|
+
updatePosition();
|
|
199
|
+
}
|
|
200
|
+
}, [open, updatePosition]);
|
|
201
|
+
useEffect(() => {
|
|
202
|
+
if (!open) return;
|
|
203
|
+
const handleClickOutside = (event) => {
|
|
204
|
+
if (dropdownRef.current && buttonRef.current && !dropdownRef.current.contains(event.target) && !buttonRef.current.contains(event.target)) {
|
|
205
|
+
setOpen(false);
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
const handleKeyDown = (event) => {
|
|
209
|
+
if (event.key === "Escape") {
|
|
210
|
+
setOpen(false);
|
|
211
|
+
}
|
|
212
|
+
};
|
|
213
|
+
const handleScroll = (event) => {
|
|
214
|
+
if (!closeOnScroll) return;
|
|
215
|
+
const target = event.target;
|
|
216
|
+
if (dropdownRef.current && target && !dropdownRef.current.contains(target) && !buttonRef.current?.contains(target)) {
|
|
217
|
+
setOpen(false);
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
document.addEventListener("mousedown", handleClickOutside);
|
|
221
|
+
document.addEventListener("keydown", handleKeyDown);
|
|
222
|
+
document.addEventListener("scroll", handleScroll, true);
|
|
223
|
+
return () => {
|
|
224
|
+
document.removeEventListener("mousedown", handleClickOutside);
|
|
225
|
+
document.removeEventListener("keydown", handleKeyDown);
|
|
226
|
+
document.removeEventListener("scroll", handleScroll, true);
|
|
227
|
+
};
|
|
228
|
+
}, [closeOnScroll, open, setOpen]);
|
|
229
|
+
const dropdownContent = open ? /* @__PURE__ */ jsx2(Dropdown1Context.Provider, { value: { closeDropdown, styles }, children: /* @__PURE__ */ jsx2(
|
|
230
|
+
"div",
|
|
231
|
+
{
|
|
232
|
+
ref: dropdownRef,
|
|
233
|
+
role: "menu",
|
|
234
|
+
"data-testid": contentTestId,
|
|
235
|
+
dir: direction,
|
|
236
|
+
className: cn2(
|
|
237
|
+
dropdown1ContentVariants(),
|
|
238
|
+
styles.content,
|
|
239
|
+
!fullWidth && contentWidth,
|
|
240
|
+
maxHeight && "overflow-y-auto",
|
|
241
|
+
contentClassName
|
|
242
|
+
),
|
|
243
|
+
style: {
|
|
244
|
+
...positionStyle,
|
|
245
|
+
zIndex: contentZIndex,
|
|
246
|
+
maxHeight: maxHeight || void 0
|
|
247
|
+
},
|
|
248
|
+
children: /* @__PURE__ */ jsx2("div", { className: "py-1", children })
|
|
249
|
+
}
|
|
250
|
+
) }) : null;
|
|
251
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
252
|
+
/* @__PURE__ */ jsx2(
|
|
253
|
+
"div",
|
|
254
|
+
{
|
|
255
|
+
className: cn2(
|
|
256
|
+
"relative text-start",
|
|
257
|
+
fullWidth ? "block w-full" : "inline-block"
|
|
258
|
+
),
|
|
259
|
+
children: /* @__PURE__ */ jsxs(
|
|
260
|
+
"button",
|
|
261
|
+
{
|
|
262
|
+
ref: buttonRef,
|
|
263
|
+
type: "button",
|
|
264
|
+
disabled,
|
|
265
|
+
"aria-expanded": open,
|
|
266
|
+
"aria-haspopup": "menu",
|
|
267
|
+
onClick: () => !disabled && setOpen(!open),
|
|
268
|
+
"data-testid": testId,
|
|
269
|
+
className: cn2(
|
|
270
|
+
dropdown1TriggerVariants({ fullWidth, disabled }),
|
|
271
|
+
styles.trigger,
|
|
272
|
+
triggerClassName
|
|
273
|
+
),
|
|
274
|
+
children: [
|
|
275
|
+
trigger,
|
|
276
|
+
/* @__PURE__ */ jsx2(ChevronDownIcon, { className: styles.triggerIcon })
|
|
277
|
+
]
|
|
278
|
+
}
|
|
279
|
+
)
|
|
280
|
+
}
|
|
281
|
+
),
|
|
282
|
+
open && /* @__PURE__ */ jsx2(Portal, { children: dropdownContent })
|
|
283
|
+
] });
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
// src/components/Dropdown1Item.tsx
|
|
287
|
+
import { cn as cn3 } from "@velocis/core";
|
|
288
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
289
|
+
function Dropdown1Item({
|
|
290
|
+
children,
|
|
291
|
+
onClick,
|
|
292
|
+
closeOnSelect = DROPDOWN1_ITEM_DEFAULTS.closeOnSelect,
|
|
293
|
+
styles: stylesProp,
|
|
294
|
+
className,
|
|
295
|
+
testId
|
|
296
|
+
}) {
|
|
297
|
+
const context = useDropdown1Context();
|
|
298
|
+
const itemStyles = stylesProp?.item ?? context?.styles.item;
|
|
299
|
+
const handleClick = () => {
|
|
300
|
+
onClick?.();
|
|
301
|
+
if (closeOnSelect && context?.closeDropdown) {
|
|
302
|
+
context.closeDropdown();
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
return /* @__PURE__ */ jsx3(
|
|
306
|
+
"div",
|
|
307
|
+
{
|
|
308
|
+
role: "menuitem",
|
|
309
|
+
tabIndex: 0,
|
|
310
|
+
onClick: handleClick,
|
|
311
|
+
onKeyDown: (e) => {
|
|
312
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
313
|
+
e.preventDefault();
|
|
314
|
+
handleClick();
|
|
315
|
+
}
|
|
316
|
+
},
|
|
317
|
+
"data-testid": testId,
|
|
318
|
+
className: cn3(dropdown1ItemVariants(), itemStyles, className),
|
|
319
|
+
children
|
|
320
|
+
}
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// src/components/Dropdown1SubMenu.tsx
|
|
325
|
+
import { cn as cn4 } from "@velocis/core";
|
|
326
|
+
import { useEffect as useEffect2, useRef as useRef2, useState as useState2 } from "react";
|
|
327
|
+
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
328
|
+
function Dropdown1SubMenu({
|
|
329
|
+
trigger,
|
|
330
|
+
children,
|
|
331
|
+
contentWidth = DROPDOWN1_SUBMENU_DEFAULTS.contentWidth,
|
|
332
|
+
styles: stylesProp,
|
|
333
|
+
className
|
|
334
|
+
}) {
|
|
335
|
+
const context = useDropdown1Context();
|
|
336
|
+
const subMenuTriggerStyles = stylesProp?.subMenuTrigger ?? context?.styles.subMenuTrigger;
|
|
337
|
+
const subMenuContentStyles = stylesProp?.subMenuContent ?? context?.styles.subMenuContent;
|
|
338
|
+
const subMenuIconStyles = stylesProp?.subMenuIcon ?? context?.styles.subMenuIcon;
|
|
339
|
+
const [isOpen, setIsOpen] = useState2(false);
|
|
340
|
+
const timeoutRef = useRef2(null);
|
|
341
|
+
const containerRef = useRef2(null);
|
|
342
|
+
const handleMouseEnter = () => {
|
|
343
|
+
if (timeoutRef.current) {
|
|
344
|
+
clearTimeout(timeoutRef.current);
|
|
345
|
+
timeoutRef.current = null;
|
|
346
|
+
}
|
|
347
|
+
setIsOpen(true);
|
|
348
|
+
};
|
|
349
|
+
const handleMouseLeave = () => {
|
|
350
|
+
timeoutRef.current = setTimeout(() => {
|
|
351
|
+
setIsOpen(false);
|
|
352
|
+
}, DROPDOWN1_SUBMENU_DEFAULTS.hoverDelayMs);
|
|
353
|
+
};
|
|
354
|
+
useEffect2(() => {
|
|
355
|
+
return () => {
|
|
356
|
+
if (timeoutRef.current) {
|
|
357
|
+
clearTimeout(timeoutRef.current);
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
}, []);
|
|
361
|
+
return /* @__PURE__ */ jsxs2(
|
|
362
|
+
"div",
|
|
363
|
+
{
|
|
364
|
+
ref: containerRef,
|
|
365
|
+
className: "relative w-full",
|
|
366
|
+
onMouseEnter: handleMouseEnter,
|
|
367
|
+
onMouseLeave: handleMouseLeave,
|
|
368
|
+
children: [
|
|
369
|
+
/* @__PURE__ */ jsxs2(
|
|
370
|
+
"div",
|
|
371
|
+
{
|
|
372
|
+
role: "menuitem",
|
|
373
|
+
"aria-haspopup": "menu",
|
|
374
|
+
"aria-expanded": isOpen,
|
|
375
|
+
className: cn4(dropdown1SubMenuTriggerVariants(), subMenuTriggerStyles),
|
|
376
|
+
children: [
|
|
377
|
+
/* @__PURE__ */ jsx4("span", { className: "flex items-center gap-2", children: trigger }),
|
|
378
|
+
/* @__PURE__ */ jsx4(ChevronSubMenuIcon, { open: isOpen, className: cn4("transition-transform", subMenuIconStyles) })
|
|
379
|
+
]
|
|
380
|
+
}
|
|
381
|
+
),
|
|
382
|
+
isOpen && /* @__PURE__ */ jsx4(
|
|
383
|
+
"div",
|
|
384
|
+
{
|
|
385
|
+
role: "menu",
|
|
386
|
+
className: cn4(
|
|
387
|
+
dropdown1SubMenuContentVariants(),
|
|
388
|
+
subMenuContentStyles,
|
|
389
|
+
contentWidth !== "w-48" && contentWidth,
|
|
390
|
+
className
|
|
391
|
+
),
|
|
392
|
+
onMouseEnter: handleMouseEnter,
|
|
393
|
+
onMouseLeave: handleMouseLeave,
|
|
394
|
+
children: /* @__PURE__ */ jsx4("div", { className: "py-1", children })
|
|
395
|
+
}
|
|
396
|
+
)
|
|
397
|
+
]
|
|
398
|
+
}
|
|
399
|
+
);
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// src/hooks/useDropdown1.ts
|
|
403
|
+
import { useCallback as useCallback2, useState as useState3 } from "react";
|
|
404
|
+
function useDropdown1(options = {}) {
|
|
405
|
+
const [open, setOpen] = useState3(options.defaultOpen ?? false);
|
|
406
|
+
const onOpenChange = useCallback2((next) => {
|
|
407
|
+
setOpen(next);
|
|
408
|
+
}, []);
|
|
409
|
+
return {
|
|
410
|
+
open,
|
|
411
|
+
setOpen,
|
|
412
|
+
dropdownProps: { open, onOpenChange }
|
|
413
|
+
};
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// src/index.ts
|
|
417
|
+
var Dropdown1 = Object.assign(Dropdown1Root, {
|
|
418
|
+
Item: Dropdown1Item,
|
|
419
|
+
SubMenu: Dropdown1SubMenu
|
|
420
|
+
});
|
|
421
|
+
export {
|
|
422
|
+
DROPDOWN1_DEFAULTS,
|
|
423
|
+
DROPDOWN1_ITEM_DEFAULTS,
|
|
424
|
+
DROPDOWN1_SUBMENU_DEFAULTS,
|
|
425
|
+
Dropdown1,
|
|
426
|
+
Dropdown1Context,
|
|
427
|
+
Dropdown1Item,
|
|
428
|
+
Dropdown1Root,
|
|
429
|
+
Dropdown1SubMenu,
|
|
430
|
+
dropdown1ContentVariants,
|
|
431
|
+
dropdown1ItemVariants,
|
|
432
|
+
dropdown1Styles,
|
|
433
|
+
dropdown1SubMenuContentVariants,
|
|
434
|
+
dropdown1SubMenuTriggerVariants,
|
|
435
|
+
dropdown1TriggerVariants,
|
|
436
|
+
resolveDropdown1Styles,
|
|
437
|
+
useDropdown1,
|
|
438
|
+
useDropdown1Context
|
|
439
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@velocis/dropdown1",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"license": "MIT",
|
|
5
|
+
"sideEffects": false,
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.cjs",
|
|
8
|
+
"module": "./dist/index.js",
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"require": "./dist/index.cjs"
|
|
15
|
+
}
|
|
16
|
+
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist"
|
|
19
|
+
],
|
|
20
|
+
"peerDependencies": {
|
|
21
|
+
"react": "^18.2.0 || ^19.0.0",
|
|
22
|
+
"react-dom": "^18.2.0 || ^19.0.0"
|
|
23
|
+
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"class-variance-authority": "^0.7.1",
|
|
26
|
+
"@velocis/core": "0.1.0",
|
|
27
|
+
"@velocis/theme": "0.1.1"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/react": "^19.0.2",
|
|
31
|
+
"eslint": "^9.17.0",
|
|
32
|
+
"react": "^19.0.0",
|
|
33
|
+
"react-dom": "^19.0.0",
|
|
34
|
+
"tsup": "^8.3.5",
|
|
35
|
+
"typescript": "^5.7.2",
|
|
36
|
+
"vitest": "^2.1.8",
|
|
37
|
+
"@velocis/tsconfig": "0.0.0",
|
|
38
|
+
"@velocis/eslint-config": "0.0.0"
|
|
39
|
+
},
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "tsup",
|
|
45
|
+
"lint": "eslint src",
|
|
46
|
+
"test": "vitest run",
|
|
47
|
+
"typecheck": "tsc --noEmit"
|
|
48
|
+
}
|
|
49
|
+
}
|