@bunnix/components 0.9.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/@types/index.d.ts +269 -0
- package/LICENSE +7 -0
- package/README.md +184 -0
- package/package.json +53 -0
- package/src/components/AccordionGroup.mjs +37 -0
- package/src/components/Badge.mjs +49 -0
- package/src/components/Button.mjs +76 -0
- package/src/components/Checkbox.mjs +36 -0
- package/src/components/ComboBox.mjs +44 -0
- package/src/components/Container.mjs +27 -0
- package/src/components/DatePicker.mjs +251 -0
- package/src/components/Dialog.mjs +166 -0
- package/src/components/DropdownMenu.mjs +110 -0
- package/src/components/Grid.mjs +40 -0
- package/src/components/HStack.mjs +34 -0
- package/src/components/Icon.mjs +32 -0
- package/src/components/InputField.mjs +78 -0
- package/src/components/NavigationBar.mjs +47 -0
- package/src/components/PageHeader.mjs +13 -0
- package/src/components/PageSection.mjs +20 -0
- package/src/components/PopoverMenu.mjs +87 -0
- package/src/components/RadioCheckbox.mjs +36 -0
- package/src/components/SearchBox.mjs +207 -0
- package/src/components/Sidebar.mjs +187 -0
- package/src/components/Table.mjs +254 -0
- package/src/components/Text.mjs +38 -0
- package/src/components/TimePicker.mjs +172 -0
- package/src/components/ToastNotification.mjs +105 -0
- package/src/components/ToggleSwitch.mjs +26 -0
- package/src/components/VStack.mjs +35 -0
- package/src/icons/add-circle.svg +1 -0
- package/src/icons/add.svg +1 -0
- package/src/icons/alt.svg +1 -0
- package/src/icons/archive.svg +1 -0
- package/src/icons/at.svg +1 -0
- package/src/icons/attestation.svg +1 -0
- package/src/icons/bell.svg +4 -0
- package/src/icons/bookmark.svg +1 -0
- package/src/icons/bot.svg +1 -0
- package/src/icons/button.svg +1 -0
- package/src/icons/calculate.svg +1 -0
- package/src/icons/calendar.svg +1 -0
- package/src/icons/chart.svg +1 -0
- package/src/icons/check.svg +1 -0
- package/src/icons/chevron-down.svg +1 -0
- package/src/icons/chevron-left.svg +1 -0
- package/src/icons/chevron-right.svg +1 -0
- package/src/icons/clip.svg +1 -0
- package/src/icons/clock.svg +4 -0
- package/src/icons/close-circle.svg +4 -0
- package/src/icons/close.svg +1 -0
- package/src/icons/cloud-download.svg +1 -0
- package/src/icons/cloud-upload.svg +1 -0
- package/src/icons/cloud.svg +1 -0
- package/src/icons/columns-layout.svg +1 -0
- package/src/icons/command.svg +1 -0
- package/src/icons/cube.svg +1 -0
- package/src/icons/delete.svg +4 -0
- package/src/icons/dollar.svg +4 -0
- package/src/icons/download.svg +1 -0
- package/src/icons/draw.svg +1 -0
- package/src/icons/duplicate.svg +4 -0
- package/src/icons/edit.svg +1 -0
- package/src/icons/exclamation-mark.svg +1 -0
- package/src/icons/eye-open.svg +1 -0
- package/src/icons/eye.svg +1 -0
- package/src/icons/file-html.svg +1 -0
- package/src/icons/file.svg +4 -0
- package/src/icons/finger.svg +1 -0
- package/src/icons/flag.svg +1 -0
- package/src/icons/folder.svg +1 -0
- package/src/icons/function.svg +1 -0
- package/src/icons/gear.svg +1 -0
- package/src/icons/gift.svg +1 -0
- package/src/icons/globe.svg +4 -0
- package/src/icons/grid.svg +1 -0
- package/src/icons/hand.svg +1 -0
- package/src/icons/heart.svg +4 -0
- package/src/icons/home.svg +4 -0
- package/src/icons/image.svg +1 -0
- package/src/icons/inbox.svg +4 -0
- package/src/icons/info.svg +1 -0
- package/src/icons/key.svg +1 -0
- package/src/icons/lamp.svg +1 -0
- package/src/icons/link.svg +1 -0
- package/src/icons/location.svg +1 -0
- package/src/icons/locker.svg +1 -0
- package/src/icons/login.svg +1 -0
- package/src/icons/logout.svg +4 -0
- package/src/icons/mail.svg +4 -0
- package/src/icons/map.svg +4 -0
- package/src/icons/markup.svg +1 -0
- package/src/icons/merge.svg +1 -0
- package/src/icons/more-horizontal.svg +5 -0
- package/src/icons/more-vertical.svg +5 -0
- package/src/icons/mouse.svg +1 -0
- package/src/icons/palette.svg +1 -0
- package/src/icons/password.svg +1 -0
- package/src/icons/pencil.svg +1 -0
- package/src/icons/people.svg +4 -0
- package/src/icons/person-add.svg +1 -0
- package/src/icons/person-remove.svg +1 -0
- package/src/icons/person.svg +5 -0
- package/src/icons/pin.svg +1 -0
- package/src/icons/question-circle.svg +4 -0
- package/src/icons/remove-circle.svg +1 -0
- package/src/icons/return-arrow.svg +2 -0
- package/src/icons/save.svg +1 -0
- package/src/icons/search.svg +1 -0
- package/src/icons/sections.svg +1 -0
- package/src/icons/send.svg +1 -0
- package/src/icons/share.svg +1 -0
- package/src/icons/shine.svg +1 -0
- package/src/icons/sliders.svg +1 -0
- package/src/icons/star.svg +4 -0
- package/src/icons/storage.svg +1 -0
- package/src/icons/success-circle.svg +4 -0
- package/src/icons/swap.svg +1 -0
- package/src/icons/switch.svg +1 -0
- package/src/icons/sync.svg +4 -0
- package/src/icons/table.svg +4 -0
- package/src/icons/tag.svg +4 -0
- package/src/icons/terminal.svg +1 -0
- package/src/icons/text.svg +1 -0
- package/src/icons/thumb-down.svg +1 -0
- package/src/icons/thumb-up.svg +1 -0
- package/src/icons/timer.svg +4 -0
- package/src/icons/toggle.svg +1 -0
- package/src/icons/trash.svg +1 -0
- package/src/icons/update-page.svg +1 -0
- package/src/icons/upload.svg +1 -0
- package/src/icons/video.svg +1 -0
- package/src/icons/wallet.svg +1 -0
- package/src/icons/window.svg +1 -0
- package/src/index.mjs +29 -0
- package/src/styles/accordion.css +70 -0
- package/src/styles/buttons.css +118 -0
- package/src/styles/colors.css +131 -0
- package/src/styles/controls.css +504 -0
- package/src/styles/datepicker.css +140 -0
- package/src/styles/interactable.css +16 -0
- package/src/styles/layout.css +444 -0
- package/src/styles/links.css +38 -0
- package/src/styles/main.css +16 -0
- package/src/styles/media.css +155 -0
- package/src/styles/menu.css +168 -0
- package/src/styles/motion.css +66 -0
- package/src/styles/table.css +78 -0
- package/src/styles/timepicker.css +87 -0
- package/src/styles/typography.css +94 -0
- package/src/styles/variables.css +218 -0
- package/src/styles.css +1 -0
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
export type BunnixChild = any;
|
|
2
|
+
export type BunnixChildren = BunnixChild | BunnixChild[];
|
|
3
|
+
|
|
4
|
+
export interface BaseProps {
|
|
5
|
+
class?: string;
|
|
6
|
+
[key: string]: unknown;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface ButtonProps extends BaseProps {
|
|
10
|
+
type?: string;
|
|
11
|
+
variant?: string;
|
|
12
|
+
size?: "sm" | "md" | "lg" | "xl" | string;
|
|
13
|
+
href?: string;
|
|
14
|
+
disabled?: boolean;
|
|
15
|
+
onClick?: (event?: any) => void;
|
|
16
|
+
click?: (event?: any) => void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface IconProps extends BaseProps {
|
|
20
|
+
name?: string;
|
|
21
|
+
fill?: string;
|
|
22
|
+
size?: "xs" | "sm" | "md" | "lg" | "xl" | string;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export interface TextProps extends BaseProps {
|
|
26
|
+
type?: "text" | "paragraph" | "heading1" | "heading2" | "heading3" | "heading4" | string;
|
|
27
|
+
color?: string;
|
|
28
|
+
design?: "regular" | "mono" | string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface ContainerProps extends BaseProps {
|
|
32
|
+
type?: "main" | "content" | "page" | string;
|
|
33
|
+
direction?: "horizontal" | "vertical" | string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export interface StackProps extends BaseProps {
|
|
37
|
+
alignment?: "leading" | "middle" | "trailing" | string;
|
|
38
|
+
gap?: "small" | "regular" | "large" | string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface BadgeProps extends BaseProps {
|
|
42
|
+
tone?: "base" | "success" | "info" | "warning" | "danger" | "accent" | "dimmed" | string;
|
|
43
|
+
size?: "xs" | "sm" | "md" | string;
|
|
44
|
+
variant?: "solid" | "soft" | "outline" | string;
|
|
45
|
+
icon?: string;
|
|
46
|
+
overlap?: boolean;
|
|
47
|
+
shape?: "capsule" | "circle" | string;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface InputFieldProps extends BaseProps {
|
|
51
|
+
type?: string;
|
|
52
|
+
variant?: "regular" | "rounded" | string;
|
|
53
|
+
value?: string;
|
|
54
|
+
placeholder?: string;
|
|
55
|
+
label?: string;
|
|
56
|
+
disabled?: boolean;
|
|
57
|
+
suggestions?: string[];
|
|
58
|
+
onInput?: (event?: any) => void;
|
|
59
|
+
onChange?: (event?: any) => void;
|
|
60
|
+
onFocus?: (event?: any) => void;
|
|
61
|
+
onBlur?: (event?: any) => void;
|
|
62
|
+
onKeyDown?: (event?: any) => void;
|
|
63
|
+
input?: (event?: any) => void;
|
|
64
|
+
change?: (event?: any) => void;
|
|
65
|
+
focus?: (event?: any) => void;
|
|
66
|
+
blur?: (event?: any) => void;
|
|
67
|
+
keydown?: (event?: any) => void;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface ComboBoxOption {
|
|
71
|
+
value: string;
|
|
72
|
+
label?: string;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface ComboBoxProps extends BaseProps {
|
|
76
|
+
options?: Array<string | ComboBoxOption>;
|
|
77
|
+
selection?: any;
|
|
78
|
+
size?: "sm" | "md" | "lg" | "xl" | string;
|
|
79
|
+
onChange?: (event?: any) => void;
|
|
80
|
+
change?: (event?: any) => void;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface CheckboxProps extends BaseProps {
|
|
84
|
+
labelText?: string;
|
|
85
|
+
size?: "sm" | "md" | "lg" | "xl" | string;
|
|
86
|
+
onCheck?: (checked: boolean) => void;
|
|
87
|
+
check?: (checked: boolean) => void;
|
|
88
|
+
onChange?: (event?: any) => void;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export interface RadioCheckboxProps extends BaseProps {
|
|
92
|
+
labelText?: string;
|
|
93
|
+
size?: "sm" | "md" | "lg" | "xl" | string;
|
|
94
|
+
onCheck?: (checked: boolean) => void;
|
|
95
|
+
check?: (checked: boolean) => void;
|
|
96
|
+
onChange?: (event?: any) => void;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export interface ToggleSwitchProps extends BaseProps {
|
|
100
|
+
labelText?: string;
|
|
101
|
+
size?: "sm" | "md" | "lg" | "xl" | string;
|
|
102
|
+
onChange?: (event?: any) => void;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export interface SearchBoxItem {
|
|
106
|
+
title?: string;
|
|
107
|
+
snippet?: string;
|
|
108
|
+
icon?: string;
|
|
109
|
+
[key: string]: unknown;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export interface SearchBoxProps extends BaseProps {
|
|
113
|
+
data?: SearchBoxItem[];
|
|
114
|
+
value?: string | any;
|
|
115
|
+
placeholder?: string;
|
|
116
|
+
onInput?: (event?: any) => void;
|
|
117
|
+
input?: (event?: any) => void;
|
|
118
|
+
size?: "sm" | "md" | "lg" | "xl" | string;
|
|
119
|
+
variant?: "regular" | "rounded" | string;
|
|
120
|
+
onSelect?: (item?: SearchBoxItem) => void;
|
|
121
|
+
select?: (item?: SearchBoxItem) => void;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export interface SidebarItem {
|
|
125
|
+
id?: string;
|
|
126
|
+
label?: string;
|
|
127
|
+
icon?: string;
|
|
128
|
+
href?: string | null;
|
|
129
|
+
badge?: string | number | { value?: string | number; tone?: string; variant?: string; size?: string };
|
|
130
|
+
children?: SidebarItem[];
|
|
131
|
+
isExpanded?: boolean;
|
|
132
|
+
isHeader?: boolean;
|
|
133
|
+
isSeparator?: boolean;
|
|
134
|
+
[key: string]: unknown;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
export interface SidebarProps extends BaseProps {
|
|
138
|
+
items?: SidebarItem[];
|
|
139
|
+
selection?: string;
|
|
140
|
+
onSelect?: (id?: string) => void;
|
|
141
|
+
onItemSelect?: (id?: string) => void;
|
|
142
|
+
searchable?: boolean;
|
|
143
|
+
searchProps?: Record<string, unknown>;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export interface NavigationBarProps extends BaseProps {
|
|
147
|
+
title?: string | (() => BunnixChildren);
|
|
148
|
+
leading?: BunnixChildren | (() => BunnixChildren);
|
|
149
|
+
trailing?: BunnixChildren | (() => BunnixChildren);
|
|
150
|
+
searchable?: boolean;
|
|
151
|
+
searchData?: SearchBoxItem[];
|
|
152
|
+
searchValue?: string | any;
|
|
153
|
+
onSearchInput?: (event?: any) => void;
|
|
154
|
+
onSearchSelect?: (item?: SearchBoxItem) => void;
|
|
155
|
+
searchProps?: Record<string, unknown>;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
export interface DatePickerProps extends BaseProps {
|
|
159
|
+
id?: string;
|
|
160
|
+
placeholder?: string;
|
|
161
|
+
range?: boolean;
|
|
162
|
+
variant?: "regular" | "rounded" | string;
|
|
163
|
+
size?: "md" | "lg" | "xl" | string;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export interface TimePickerProps extends BaseProps {
|
|
167
|
+
id?: string;
|
|
168
|
+
placeholder?: string;
|
|
169
|
+
variant?: "regular" | "rounded" | string;
|
|
170
|
+
size?: "md" | "lg" | "xl" | string;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export interface DropdownMenuItem {
|
|
174
|
+
title?: string;
|
|
175
|
+
icon?: string;
|
|
176
|
+
destructive?: boolean;
|
|
177
|
+
isSeparator?: boolean;
|
|
178
|
+
selected?: boolean;
|
|
179
|
+
click?: () => void;
|
|
180
|
+
[key: string]: unknown;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export interface DropdownMenuProps extends BaseProps {
|
|
184
|
+
items?: DropdownMenuItem[];
|
|
185
|
+
id?: string;
|
|
186
|
+
align?: "left" | "right" | string;
|
|
187
|
+
placeholder?: string;
|
|
188
|
+
size?: "sm" | "md" | "lg" | "xl" | string;
|
|
189
|
+
onSelect?: (item?: DropdownMenuItem) => void;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export interface PopoverMenuProps extends BaseProps {
|
|
193
|
+
trigger?: BunnixChildren;
|
|
194
|
+
items?: DropdownMenuItem[];
|
|
195
|
+
id?: string;
|
|
196
|
+
align?: "left" | "right" | string;
|
|
197
|
+
size?: "sm" | "md" | "lg" | "xl" | string;
|
|
198
|
+
onSelect?: (item?: DropdownMenuItem) => void;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
export interface DialogConfirmation {
|
|
202
|
+
text?: string;
|
|
203
|
+
action?: () => void;
|
|
204
|
+
variant?: string;
|
|
205
|
+
disabled?: boolean;
|
|
206
|
+
extra?: { text?: string; action?: () => void };
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export interface ShowDialogOptions {
|
|
210
|
+
title?: string;
|
|
211
|
+
message?: string;
|
|
212
|
+
confirmation?: DialogConfirmation;
|
|
213
|
+
content?: (args: { setConfirmDisabled: (disabled: boolean) => void }) => BunnixChildren;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export interface ToastOptions {
|
|
217
|
+
message?: string;
|
|
218
|
+
duration?: number;
|
|
219
|
+
anchor?: "topRight" | "topLeft" | "bottomRight" | "bottomLeft" | string;
|
|
220
|
+
size?: "md" | "lg" | "xl" | string;
|
|
221
|
+
icon?: string;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
export type Component<P = BaseProps> = (props?: P, children?: BunnixChildren) => any;
|
|
225
|
+
|
|
226
|
+
export const AccordionGroup: Component<BaseProps>;
|
|
227
|
+
export const Badge: Component<BadgeProps>;
|
|
228
|
+
export const Button: Component<ButtonProps>;
|
|
229
|
+
export const Checkbox: Component<CheckboxProps>;
|
|
230
|
+
export const ComboBox: Component<ComboBoxProps>;
|
|
231
|
+
export const Container: Component<ContainerProps>;
|
|
232
|
+
export const DatePicker: Component<DatePickerProps>;
|
|
233
|
+
export const Dialog: Component<BaseProps>;
|
|
234
|
+
export const DropdownMenu: Component<DropdownMenuProps>;
|
|
235
|
+
export const Grid: Component<BaseProps>;
|
|
236
|
+
export const HStack: Component<StackProps>;
|
|
237
|
+
export const Icon: Component<IconProps>;
|
|
238
|
+
export const InputField: Component<InputFieldProps>;
|
|
239
|
+
export const NavigationBar: Component<NavigationBarProps>;
|
|
240
|
+
export const PageHeader: Component<BaseProps>;
|
|
241
|
+
export const PageSection: Component<BaseProps>;
|
|
242
|
+
export const PopoverMenu: Component<PopoverMenuProps>;
|
|
243
|
+
export const RadioCheckbox: Component<RadioCheckboxProps>;
|
|
244
|
+
export const SearchBox: Component<SearchBoxProps>;
|
|
245
|
+
export const Sidebar: Component<SidebarProps>;
|
|
246
|
+
export const Table: Component<BaseProps>;
|
|
247
|
+
export const Text: Component<TextProps>;
|
|
248
|
+
export const TimePicker: Component<TimePickerProps>;
|
|
249
|
+
export const ToastNotification: Component<BaseProps>;
|
|
250
|
+
export const ToggleSwitch: Component<ToggleSwitchProps>;
|
|
251
|
+
export const VStack: Component<StackProps>;
|
|
252
|
+
|
|
253
|
+
export const dialogState: any;
|
|
254
|
+
export function showDialog(options?: ShowDialogOptions): void;
|
|
255
|
+
export function hideDialog(): void;
|
|
256
|
+
|
|
257
|
+
export const toastState: any;
|
|
258
|
+
export function showToast(options?: ToastOptions): void;
|
|
259
|
+
export function hideToast(): void;
|
|
260
|
+
|
|
261
|
+
declare module "@bunnix/components/styles.css" {
|
|
262
|
+
const content: string;
|
|
263
|
+
export default content;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
declare module "@bunnix/components/styles" {
|
|
267
|
+
const content: string;
|
|
268
|
+
export default content;
|
|
269
|
+
}
|
package/LICENSE
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Morisson Maciel
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
# @bunnix/components
|
|
2
|
+
|
|
3
|
+
Design system + UI components for Bunnix projects. This package ships ESM source with CSS + icon assets and is intended for modern, module-based builds (webpack/vite/rollup/etc).
|
|
4
|
+
|
|
5
|
+
Disclaimer:
|
|
6
|
+
- This project is currently in **alpha release candidate**. APIs and components may change until the first stable release.
|
|
7
|
+
- Icon usage & attribution:
|
|
8
|
+
- COLLECTION: Framework7 Line Icons — LICENSE: MIT License — AUTHOR: framework7io
|
|
9
|
+
- COLLECTION: Iconcino Interface Icons — LICENSE: CC0 1.0 — AUTHOR: Gabriele Malaspina
|
|
10
|
+
- Sources (copy/paste): `https://framework7.io/icons/` and `https://iconcino.com/`
|
|
11
|
+
|
|
12
|
+
## Install
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
npm install @bunnix/components @bunnix/core
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
`@bunnix/core` is a peer dependency (required by design).
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
Import the CSS once at your app entry:
|
|
23
|
+
|
|
24
|
+
```js
|
|
25
|
+
import "@bunnix/components/styles.css";
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Then import components as needed:
|
|
29
|
+
|
|
30
|
+
```js
|
|
31
|
+
import { Button, Icon, Text } from "@bunnix/components";
|
|
32
|
+
|
|
33
|
+
export default function Example() {
|
|
34
|
+
return Button({ variant: "regular" }, [
|
|
35
|
+
Icon({ name: "star", fill: "white" }),
|
|
36
|
+
Text({ type: "text" }, "Star")
|
|
37
|
+
]);
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Component examples
|
|
42
|
+
|
|
43
|
+
Button with icon:
|
|
44
|
+
|
|
45
|
+
```js
|
|
46
|
+
import { Button, Icon } from "@bunnix/components";
|
|
47
|
+
|
|
48
|
+
Button({ variant: "regular" }, [
|
|
49
|
+
Icon({ name: "star", fill: "white" }),
|
|
50
|
+
"Star"
|
|
51
|
+
]);
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
Search box with suggestions:
|
|
55
|
+
|
|
56
|
+
```js
|
|
57
|
+
import { SearchBox } from "@bunnix/components";
|
|
58
|
+
|
|
59
|
+
SearchBox({
|
|
60
|
+
data: [
|
|
61
|
+
{ title: "Users", snippet: "Manage users", icon: "person" },
|
|
62
|
+
{ title: "Settings", snippet: "Configure app", icon: "gear" }
|
|
63
|
+
]
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
Dialog + toast helpers:
|
|
68
|
+
|
|
69
|
+
```js
|
|
70
|
+
import { Dialog, showDialog, ToastNotification, showToast } from "@bunnix/components";
|
|
71
|
+
|
|
72
|
+
showDialog({ title: "Welcome", message: "Bunnix components ready." });
|
|
73
|
+
showToast({ message: "Saved successfully", icon: "success-circle" });
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Assets (icons)
|
|
77
|
+
|
|
78
|
+
SVG icons are shipped with the package and referenced by CSS variables. If your bundler rewrites asset URLs, make sure it processes CSS `url(...)` values from `@bunnix/components`.
|
|
79
|
+
|
|
80
|
+
## Theming
|
|
81
|
+
|
|
82
|
+
Override CSS variables after importing the stylesheet:
|
|
83
|
+
|
|
84
|
+
```css
|
|
85
|
+
:root {
|
|
86
|
+
--accent-color: #2563eb;
|
|
87
|
+
--background-color: #ffffff;
|
|
88
|
+
--border-color: #e5e7eb;
|
|
89
|
+
--base-padding: 0.75rem;
|
|
90
|
+
--base-gap: 0.6rem;
|
|
91
|
+
--font-family: "Inter", system-ui, sans-serif;
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## CSS modifiers (utilities)
|
|
96
|
+
|
|
97
|
+
You can compose your own UI using the same CSS utilities the components use:
|
|
98
|
+
|
|
99
|
+
- Layout: `row-container`, `column-container`, `grid-flow`, `gap-xs|sm|md|lg`, `items-start|center|end|stretch`, `justify-start|center|end`, `w-full`, `h-full`, `spacer-h`, `spacer-v`
|
|
100
|
+
- Surfaces: `box`, `box-sm`, `box-control`, `box-capsule`, `card`, `shadow`, `rounded|rounded-sm|rounded-full`
|
|
101
|
+
- Typography: `text-primary|secondary|tertiary|quaternary`, `text-accent`, `text-destructive`, `text-sm|base|lg|xl`, `text-mono`, `whitespace-nowrap`, `whitespace-pre-line`
|
|
102
|
+
- Buttons: `btn`, `btn-flat`, `btn-outline`, `btn-destructive`, `btn-lg`, `btn-xl`, `btn-disabled`
|
|
103
|
+
- Forms: `input-lg`, `input-xl`, `rounded-full` (useful for pill inputs)
|
|
104
|
+
- Icons: `icon`, `icon-<name>`, `icon-xs|sm|lg|xl`, `icon-base|white|secondary|tertiary|quaternary`
|
|
105
|
+
|
|
106
|
+
Example:
|
|
107
|
+
|
|
108
|
+
```js
|
|
109
|
+
import Bunnix from "@bunnix/core";
|
|
110
|
+
const { div, span } = Bunnix;
|
|
111
|
+
|
|
112
|
+
div({ class: "card row-container gap-sm items-center" }, [
|
|
113
|
+
span({ class: "icon icon-star icon-base icon-sm" }),
|
|
114
|
+
span({ class: "text-primary text-sm" }, "Custom card")
|
|
115
|
+
]);
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
## Minimal webpack config
|
|
119
|
+
|
|
120
|
+
This is a minimal setup that works with `@bunnix/components` (ESM, CSS, and SVG assets):
|
|
121
|
+
|
|
122
|
+
```js
|
|
123
|
+
import path from "path";
|
|
124
|
+
import { fileURLToPath } from "url";
|
|
125
|
+
import HtmlWebpackPlugin from "html-webpack-plugin";
|
|
126
|
+
|
|
127
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
128
|
+
const __dirname = path.dirname(__filename);
|
|
129
|
+
|
|
130
|
+
export default {
|
|
131
|
+
entry: "./src/index.mjs",
|
|
132
|
+
output: {
|
|
133
|
+
filename: "main.js",
|
|
134
|
+
path: path.resolve(__dirname, "dist"),
|
|
135
|
+
clean: true,
|
|
136
|
+
assetModuleFilename: "images/[hash][ext][query]"
|
|
137
|
+
},
|
|
138
|
+
mode: "development",
|
|
139
|
+
module: {
|
|
140
|
+
rules: [
|
|
141
|
+
{ test: /\\.css$/i, use: ["style-loader", "css-loader"] },
|
|
142
|
+
{ test: /\\.(png|svg|jpg|jpeg|gif)$/i, type: "asset/resource" }
|
|
143
|
+
]
|
|
144
|
+
},
|
|
145
|
+
resolve: {
|
|
146
|
+
extensions: [".mjs", ".js", ".json"]
|
|
147
|
+
},
|
|
148
|
+
plugins: [
|
|
149
|
+
new HtmlWebpackPlugin({ template: "./public/index.html" })
|
|
150
|
+
],
|
|
151
|
+
devServer: {
|
|
152
|
+
static: { directory: path.join(__dirname, "public") },
|
|
153
|
+
compress: true,
|
|
154
|
+
port: 3000,
|
|
155
|
+
open: true
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
## Project structure
|
|
161
|
+
|
|
162
|
+
```
|
|
163
|
+
src/
|
|
164
|
+
components/ # exported components
|
|
165
|
+
styles/ # design system CSS
|
|
166
|
+
icons/ # SVG assets
|
|
167
|
+
index.mjs # package exports
|
|
168
|
+
styles.css # CSS entry
|
|
169
|
+
playgrounds/ # local showcase (uses the package)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Playground
|
|
173
|
+
|
|
174
|
+
The playground consumes `@bunnix/components` directly. Start it with your preferred dev server (whatever you use today), and ensure the CSS import stays at `playgrounds/src/index.mjs`.
|
|
175
|
+
|
|
176
|
+
## Publishing notes
|
|
177
|
+
|
|
178
|
+
- This package targets ESM consumers and ships source files (no dist build).
|
|
179
|
+
- Ensure `files` and `exports` in `package.json` include `src/` and CSS entries.
|
|
180
|
+
- GitHub CI should run with Node that supports ESM (Node 16+ recommended).
|
|
181
|
+
|
|
182
|
+
## License
|
|
183
|
+
|
|
184
|
+
ISC
|
package/package.json
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@bunnix/components",
|
|
3
|
+
"version": "0.9.0",
|
|
4
|
+
"description": "Bunnix components: a set of bunnix ready components for modern web apps.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"bunnix",
|
|
7
|
+
"componentes",
|
|
8
|
+
"reactive",
|
|
9
|
+
"stateful",
|
|
10
|
+
"web",
|
|
11
|
+
"app"
|
|
12
|
+
],
|
|
13
|
+
"homepage": "https://github.com/bunnix-js/bunnix-components#readme",
|
|
14
|
+
"bugs": {
|
|
15
|
+
"url": "https://github.com/bunnix-js/bunnix-components/issues"
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "git+https://github.com/bunnix-js/bunnix-components.git"
|
|
20
|
+
},
|
|
21
|
+
"license": "ISC",
|
|
22
|
+
"author": "@bunnix",
|
|
23
|
+
"type": "module",
|
|
24
|
+
"main": "src/index.mjs",
|
|
25
|
+
"style": "src/styles.css",
|
|
26
|
+
"types": "@types/index.d.ts",
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./@types/index.d.ts",
|
|
30
|
+
"default": "./src/index.mjs"
|
|
31
|
+
},
|
|
32
|
+
"./styles": "./src/styles.css",
|
|
33
|
+
"./styles.css": "./src/styles.css",
|
|
34
|
+
"./icons/*": "./src/icons/*"
|
|
35
|
+
},
|
|
36
|
+
"sideEffects": [
|
|
37
|
+
"./src/styles.css",
|
|
38
|
+
"./src/styles/*.css"
|
|
39
|
+
],
|
|
40
|
+
"files": [
|
|
41
|
+
"src",
|
|
42
|
+
"@types"
|
|
43
|
+
],
|
|
44
|
+
"scripts": {
|
|
45
|
+
"test": "node --test"
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"@bunnix/core": "^0.9.4"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@bunnix/core": "^0.9.4"
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import Bunnix, { useState } from "@bunnix/core";
|
|
2
|
+
const { div, button, span, p } = Bunnix;
|
|
3
|
+
|
|
4
|
+
export default function AccordionGroup({ items = [], class: className = "", initialIndex } = {}) {
|
|
5
|
+
const resolvedInitial = Number.isInteger(initialIndex)
|
|
6
|
+
? initialIndex
|
|
7
|
+
: items.findIndex((item) => item?.open);
|
|
8
|
+
const openIndex = useState(resolvedInitial >= 0 ? resolvedInitial : null);
|
|
9
|
+
|
|
10
|
+
const handleToggle = (index) => {
|
|
11
|
+
const current = openIndex.get();
|
|
12
|
+
openIndex.set(current === index ? null : index);
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
return div(
|
|
16
|
+
{ class: `accordion-group ${className}`.trim() },
|
|
17
|
+
items.map((item, index) => {
|
|
18
|
+
const isOpen = openIndex.map((value) => value === index);
|
|
19
|
+
const iconClass = item.icon ? item.icon : "icon-add";
|
|
20
|
+
const description = item.description ?? item.content ?? "";
|
|
21
|
+
|
|
22
|
+
return div({ class: isOpen.map((open) => `accordion-item hoverable ${open ? "accordion-open" : ""}`) }, [
|
|
23
|
+
button({ class: "accordion-header", click: () => handleToggle(index) }, [
|
|
24
|
+
span({ class: isOpen.map((open) => `icon accordion-icon ${iconClass} ${open ? "bg-accent" : "bg-primary"}`) }),
|
|
25
|
+
span({ class: "accordion-title" }, item.title)
|
|
26
|
+
]),
|
|
27
|
+
div({ class: "accordion-content" }, [
|
|
28
|
+
div({ class: "accordion-body" }, [
|
|
29
|
+
typeof description === "string"
|
|
30
|
+
? p({ class: "accordion-description" }, description)
|
|
31
|
+
: description
|
|
32
|
+
])
|
|
33
|
+
])
|
|
34
|
+
]);
|
|
35
|
+
})
|
|
36
|
+
);
|
|
37
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import Bunnix from "@bunnix/core";
|
|
2
|
+
import Icon from "./Icon.mjs";
|
|
3
|
+
|
|
4
|
+
const { span } = Bunnix;
|
|
5
|
+
|
|
6
|
+
const toneClassMap = {
|
|
7
|
+
base: "badge-base",
|
|
8
|
+
success: "badge-success",
|
|
9
|
+
info: "badge-info",
|
|
10
|
+
warning: "badge-warning",
|
|
11
|
+
danger: "badge-danger",
|
|
12
|
+
accent: "badge-accent",
|
|
13
|
+
dimmed: "badge-dimmed"
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const sizeClassMap = {
|
|
17
|
+
xs: "badge-xs",
|
|
18
|
+
sm: "badge-sm",
|
|
19
|
+
md: "badge-md"
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const variantClassMap = {
|
|
23
|
+
solid: "badge-solid",
|
|
24
|
+
soft: "badge-soft",
|
|
25
|
+
outline: "badge-outline"
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export default function Badge({
|
|
29
|
+
tone = "base",
|
|
30
|
+
size = "sm",
|
|
31
|
+
variant = "solid",
|
|
32
|
+
icon,
|
|
33
|
+
overlap = false,
|
|
34
|
+
shape = "capsule",
|
|
35
|
+
class: className = ""
|
|
36
|
+
} = {}, children) {
|
|
37
|
+
const toneClass = toneClassMap[tone] || toneClassMap.base;
|
|
38
|
+
const sizeClass = sizeClassMap[size] || sizeClassMap.sm;
|
|
39
|
+
const variantClass = variantClassMap[variant] || variantClassMap.solid;
|
|
40
|
+
const iconSize = size === "md" ? "lg" : size === "xs" ? "xs" : "sm";
|
|
41
|
+
const overlapClass = overlap ? "badge-overlap" : "";
|
|
42
|
+
const shapeClass = shape === "circle" ? "badge-circle" : "";
|
|
43
|
+
const combinedClass = `badge ${toneClass} ${sizeClass} ${variantClass} ${overlapClass} ${shapeClass} ${className}`.trim();
|
|
44
|
+
|
|
45
|
+
return span({ class: combinedClass }, [
|
|
46
|
+
icon ? Icon({ name: icon, fill: "current", size: iconSize }) : null,
|
|
47
|
+
children
|
|
48
|
+
]);
|
|
49
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import Bunnix from "@bunnix/core";
|
|
2
|
+
const { button, a } = Bunnix;
|
|
3
|
+
|
|
4
|
+
export default function Button({
|
|
5
|
+
type = "button",
|
|
6
|
+
variant = "regular",
|
|
7
|
+
size,
|
|
8
|
+
href,
|
|
9
|
+
disabled = false,
|
|
10
|
+
onClick,
|
|
11
|
+
click,
|
|
12
|
+
class: className = "",
|
|
13
|
+
...rest
|
|
14
|
+
} = {}, children) {
|
|
15
|
+
const normalizeSize = (value) => {
|
|
16
|
+
if (!value || value === "default" || value === "regular" || value === "md") return "md";
|
|
17
|
+
if (value === "sm") return "sm";
|
|
18
|
+
if (value === "lg" || value === "xl") return value;
|
|
19
|
+
return value;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const variantState = variant && typeof variant.map === "function" ? variant : null;
|
|
23
|
+
const sizeState = size && typeof size.map === "function" ? size : null;
|
|
24
|
+
const disabledState = disabled && typeof disabled.map === "function" ? disabled : null;
|
|
25
|
+
const resolvedVariant = variantState ? variantState.get() : variant;
|
|
26
|
+
const isHyperlink = resolvedVariant === "hyperlink";
|
|
27
|
+
const handler = onClick ?? click;
|
|
28
|
+
|
|
29
|
+
const buildClass = (variantValue, sizeValue, disabledValue) => {
|
|
30
|
+
const normalizedSize = normalizeSize(sizeValue);
|
|
31
|
+
const baseClass = isHyperlink ? "" : "btn";
|
|
32
|
+
const variantClass = (isHyperlink || variantValue === "regular") ? "" : `btn-${variantValue}`;
|
|
33
|
+
const sizeClass = (!isHyperlink && normalizedSize && normalizedSize !== "md" && (normalizedSize === "lg" || normalizedSize === "xl"))
|
|
34
|
+
? `btn-${normalizedSize}`
|
|
35
|
+
: "";
|
|
36
|
+
const disabledClass = disabledValue ? "btn-disabled" : "";
|
|
37
|
+
return `${baseClass} ${variantClass} ${sizeClass} ${disabledClass} ${className}`.trim();
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
const combinedClass = variantState
|
|
41
|
+
? variantState.map((value) =>
|
|
42
|
+
buildClass(value, sizeState ? sizeState.get() : size, disabledState ? disabledState.get() : disabled)
|
|
43
|
+
)
|
|
44
|
+
: sizeState
|
|
45
|
+
? sizeState.map((value) =>
|
|
46
|
+
buildClass(resolvedVariant, value, disabledState ? disabledState.get() : disabled)
|
|
47
|
+
)
|
|
48
|
+
: disabledState
|
|
49
|
+
? disabledState.map((value) => buildClass(resolvedVariant, size, value))
|
|
50
|
+
: buildClass(resolvedVariant, size, disabled);
|
|
51
|
+
|
|
52
|
+
const props = {
|
|
53
|
+
class: combinedClass,
|
|
54
|
+
disabled,
|
|
55
|
+
...rest
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
// Only attach click handler if not disabled
|
|
59
|
+
if (handler) {
|
|
60
|
+
props.click = (event) => {
|
|
61
|
+
const isDisabled = disabledState ? disabledState.get() : !!disabled;
|
|
62
|
+
if (isDisabled) return;
|
|
63
|
+
handler(event);
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (type === "link" || isHyperlink) {
|
|
68
|
+
// If it's a hyperlink variant, default to link type unless explicitly button
|
|
69
|
+
if (!disabled) {
|
|
70
|
+
props.href = href || "#";
|
|
71
|
+
}
|
|
72
|
+
return a(props, children);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
return button(props, children);
|
|
76
|
+
}
|