@bunnix/components 0.9.1 → 0.9.2

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.
Files changed (41) hide show
  1. package/@types/index.d.ts +126 -30
  2. package/README.md +2 -2
  3. package/package.json +1 -1
  4. package/src/components/AccordionGroup.mjs +2 -1
  5. package/src/components/Badge.mjs +18 -4
  6. package/src/components/Button.mjs +7 -9
  7. package/src/components/Card.mjs +37 -0
  8. package/src/components/Checkbox.mjs +5 -7
  9. package/src/components/ComboBox.mjs +22 -14
  10. package/src/components/Container.mjs +8 -10
  11. package/src/components/DatePicker.mjs +13 -15
  12. package/src/components/Dialog.mjs +35 -4
  13. package/src/components/DropdownMenu.mjs +16 -14
  14. package/src/components/HStack.mjs +11 -3
  15. package/src/components/Icon.mjs +9 -5
  16. package/src/components/InputField.mjs +12 -4
  17. package/src/components/NavigationBar.mjs +55 -25
  18. package/src/components/PageHeader.mjs +11 -8
  19. package/src/components/PageSection.mjs +20 -10
  20. package/src/components/PopoverMenu.mjs +94 -50
  21. package/src/components/RadioCheckbox.mjs +5 -7
  22. package/src/components/SearchBox.mjs +12 -21
  23. package/src/components/Sidebar.mjs +142 -67
  24. package/src/components/Table.mjs +145 -96
  25. package/src/components/Text.mjs +52 -21
  26. package/src/components/TimePicker.mjs +13 -15
  27. package/src/components/ToastNotification.mjs +16 -13
  28. package/src/components/ToggleSwitch.mjs +5 -7
  29. package/src/components/VStack.mjs +7 -6
  30. package/src/index.mjs +1 -0
  31. package/src/styles/buttons.css +8 -0
  32. package/src/styles/colors.css +8 -0
  33. package/src/styles/controls.css +38 -2
  34. package/src/styles/layout.css +64 -5
  35. package/src/styles/media.css +11 -0
  36. package/src/styles/menu.css +39 -21
  37. package/src/styles/table.css +2 -2
  38. package/src/styles/typography.css +25 -0
  39. package/src/styles/variables.css +3 -0
  40. package/src/utils/iconUtils.mjs +10 -0
  41. package/src/utils/sizeUtils.mjs +87 -0
package/@types/index.d.ts CHANGED
@@ -6,10 +6,16 @@ export interface BaseProps {
6
6
  [key: string]: unknown;
7
7
  }
8
8
 
9
+ export type Size = "xsmall" | "small" | "regular" | "large" | "xlarge";
10
+ export type LegacySize = "xs" | "sm" | "md" | "lg" | "xl" | "default";
11
+ export type SizeValue = Size | LegacySize;
12
+ export type SizeNoSmall = Exclude<SizeValue, "small" | "sm">;
13
+ export type SizeRegularUp = Exclude<SizeValue, "xsmall" | "xs" | "small" | "sm">;
14
+
9
15
  export interface ButtonProps extends BaseProps {
10
16
  type?: string;
11
17
  variant?: string;
12
- size?: "sm" | "md" | "lg" | "xl" | string;
18
+ size?: SizeValue;
13
19
  href?: string;
14
20
  disabled?: boolean;
15
21
  onClick?: (event?: any) => void;
@@ -19,28 +25,53 @@ export interface ButtonProps extends BaseProps {
19
25
  export interface IconProps extends BaseProps {
20
26
  name?: string;
21
27
  fill?: string;
22
- size?: "xs" | "sm" | "md" | "lg" | "xl" | string;
28
+ size?: SizeValue | `icon-${string}`;
23
29
  }
24
30
 
25
31
  export interface TextProps extends BaseProps {
26
- type?: "text" | "paragraph" | "heading1" | "heading2" | "heading3" | "heading4" | string;
27
- color?: string;
28
- design?: "regular" | "mono" | string;
32
+ type?: "text" | "paragraph" | "heading1" | "heading2" | "heading3" | "heading4";
33
+ color?: "default"
34
+ | "primary"
35
+ | "primary-dimmed"
36
+ | "secondary"
37
+ | "tertiary"
38
+ | "quaternary"
39
+ | "destructive"
40
+ | "destructive-dimmed"
41
+ | "accent"
42
+ | "accent-dimmed"
43
+ | "white"
44
+ | (string & {});
45
+ design?: "regular" | "mono";
46
+ weight?: "regular" | "semibold" | "bold";
47
+ size?: SizeValue;
48
+ wrap?: "wrap" | "nowrap";
29
49
  }
30
50
 
31
51
  export interface ContainerProps extends BaseProps {
32
- type?: "main" | "content" | "page" | string;
33
- direction?: "horizontal" | "vertical" | string;
52
+ type?: "main" | "content" | "page" | (string & {});
53
+ direction?: "row" | "column" | (string & {});
34
54
  }
35
55
 
36
- export interface StackProps extends BaseProps {
56
+ export interface CardProps extends BaseProps {
57
+ direction?: "horizontal" | "vertical" | string;
37
58
  alignment?: "leading" | "middle" | "trailing" | string;
38
- gap?: "small" | "regular" | "large" | string;
59
+ }
60
+
61
+ export interface HStackProps extends BaseProps {
62
+ alignment?: "leading" | "middle" | "trailing" | (string & {});
63
+ verticalAlignment?: "top" | "center" | "bottom" | (string & {});
64
+ gap?: "xsmall" | "small" | "regular" | "large" | (string & {});
65
+ }
66
+
67
+ export interface VStackProps extends BaseProps {
68
+ alignment?: "leading" | "middle" | "trailing" | (string & {});
69
+ gap?: "xsmall" | "small" | "regular" | "large" | (string & {});
39
70
  }
40
71
 
41
72
  export interface BadgeProps extends BaseProps {
42
73
  tone?: "base" | "success" | "info" | "warning" | "danger" | "accent" | "dimmed" | string;
43
- size?: "xs" | "sm" | "md" | string;
74
+ size?: SizeValue;
44
75
  variant?: "solid" | "soft" | "outline" | string;
45
76
  icon?: string;
46
77
  overlap?: boolean;
@@ -50,6 +81,7 @@ export interface BadgeProps extends BaseProps {
50
81
  export interface InputFieldProps extends BaseProps {
51
82
  type?: string;
52
83
  variant?: "regular" | "rounded" | string;
84
+ size?: SizeRegularUp;
53
85
  value?: string;
54
86
  placeholder?: string;
55
87
  label?: string;
@@ -82,14 +114,14 @@ export interface ComboBoxOption {
82
114
  export interface ComboBoxProps extends BaseProps {
83
115
  options?: Array<string | ComboBoxOption>;
84
116
  selection?: any;
85
- size?: "sm" | "md" | "lg" | "xl" | string;
117
+ size?: SizeValue;
86
118
  onChange?: (event?: any) => void;
87
119
  change?: (event?: any) => void;
88
120
  }
89
121
 
90
122
  export interface CheckboxProps extends BaseProps {
91
123
  labelText?: string;
92
- size?: "sm" | "md" | "lg" | "xl" | string;
124
+ size?: SizeValue;
93
125
  onCheck?: (checked: boolean) => void;
94
126
  check?: (checked: boolean) => void;
95
127
  onChange?: (event?: any) => void;
@@ -97,7 +129,7 @@ export interface CheckboxProps extends BaseProps {
97
129
 
98
130
  export interface RadioCheckboxProps extends BaseProps {
99
131
  labelText?: string;
100
- size?: "sm" | "md" | "lg" | "xl" | string;
132
+ size?: SizeValue;
101
133
  onCheck?: (checked: boolean) => void;
102
134
  check?: (checked: boolean) => void;
103
135
  onChange?: (event?: any) => void;
@@ -105,7 +137,7 @@ export interface RadioCheckboxProps extends BaseProps {
105
137
 
106
138
  export interface ToggleSwitchProps extends BaseProps {
107
139
  labelText?: string;
108
- size?: "sm" | "md" | "lg" | "xl" | string;
140
+ size?: SizeValue;
109
141
  onChange?: (event?: any) => void;
110
142
  }
111
143
 
@@ -122,7 +154,7 @@ export interface SearchBoxProps extends BaseProps {
122
154
  placeholder?: string;
123
155
  onInput?: (event?: any) => void;
124
156
  input?: (event?: any) => void;
125
- size?: "sm" | "md" | "lg" | "xl" | string;
157
+ size?: SizeValue;
126
158
  variant?: "regular" | "rounded" | string;
127
159
  onSelect?: (item?: SearchBoxItem) => void;
128
160
  select?: (item?: SearchBoxItem) => void;
@@ -131,9 +163,13 @@ export interface SearchBoxProps extends BaseProps {
131
163
  export interface SidebarItem {
132
164
  id?: string;
133
165
  label?: string;
166
+ /**
167
+ * Icon name. Accepts either a full icon class (e.g. "icon-person")
168
+ * or a bare name (e.g. "person"), which will be prefixed with "icon-".
169
+ */
134
170
  icon?: string;
135
171
  href?: string | null;
136
- badge?: string | number | { value?: string | number; tone?: string; variant?: string; size?: string };
172
+ badge?: string | number | { value?: string | number; tone?: string; variant?: string; size?: SizeValue };
137
173
  children?: SidebarItem[];
138
174
  isExpanded?: boolean;
139
175
  isHeader?: boolean;
@@ -143,15 +179,18 @@ export interface SidebarItem {
143
179
 
144
180
  export interface SidebarProps extends BaseProps {
145
181
  items?: SidebarItem[];
146
- selection?: string;
182
+ selection?: string | any;
183
+ /** @deprecated Use onItemSelect instead. */
147
184
  onSelect?: (id?: string) => void;
148
185
  onItemSelect?: (id?: string) => void;
149
186
  searchable?: boolean;
150
187
  searchProps?: Record<string, unknown>;
188
+ leading?: BunnixChildren | (() => BunnixChildren);
189
+ trailing?: BunnixChildren | (() => BunnixChildren);
151
190
  }
152
191
 
153
192
  export interface NavigationBarProps extends BaseProps {
154
- title?: string | (() => BunnixChildren);
193
+ title?: string | any;
155
194
  leading?: BunnixChildren | (() => BunnixChildren);
156
195
  trailing?: BunnixChildren | (() => BunnixChildren);
157
196
  searchable?: boolean;
@@ -167,18 +206,22 @@ export interface DatePickerProps extends BaseProps {
167
206
  placeholder?: string;
168
207
  range?: boolean;
169
208
  variant?: "regular" | "rounded" | string;
170
- size?: "md" | "lg" | "xl" | string;
209
+ size?: SizeNoSmall;
171
210
  }
172
211
 
173
212
  export interface TimePickerProps extends BaseProps {
174
213
  id?: string;
175
214
  placeholder?: string;
176
215
  variant?: "regular" | "rounded" | string;
177
- size?: "md" | "lg" | "xl" | string;
216
+ size?: SizeNoSmall;
178
217
  }
179
218
 
180
219
  export interface DropdownMenuItem {
181
220
  title?: string;
221
+ /**
222
+ * Icon name. Accepts either a full icon class (e.g. "icon-person")
223
+ * or a bare name (e.g. "person"), which will be prefixed with "icon-".
224
+ */
182
225
  icon?: string;
183
226
  destructive?: boolean;
184
227
  isSeparator?: boolean;
@@ -192,16 +235,16 @@ export interface DropdownMenuProps extends BaseProps {
192
235
  id?: string;
193
236
  align?: "left" | "right" | string;
194
237
  placeholder?: string;
195
- size?: "sm" | "md" | "lg" | "xl" | string;
238
+ size?: SizeValue;
196
239
  onSelect?: (item?: DropdownMenuItem) => void;
197
240
  }
198
241
 
199
242
  export interface PopoverMenuProps extends BaseProps {
200
- trigger?: BunnixChildren;
201
- items?: DropdownMenuItem[];
243
+ trigger?: BunnixChildren | (() => BunnixChildren);
244
+ menuItems?: DropdownMenuItem[];
202
245
  id?: string;
203
246
  align?: "left" | "right" | string;
204
- size?: "sm" | "md" | "lg" | "xl" | string;
247
+ size?: SizeValue;
205
248
  onSelect?: (item?: DropdownMenuItem) => void;
206
249
  }
207
250
 
@@ -216,6 +259,8 @@ export interface DialogConfirmation {
216
259
  export interface ShowDialogOptions {
217
260
  title?: string;
218
261
  message?: string;
262
+ minWidth?: number | string | null;
263
+ minHeight?: number | string | null;
219
264
  confirmation?: DialogConfirmation;
220
265
  content?: (args: { setConfirmDisabled: (disabled: boolean) => void }) => BunnixChildren;
221
266
  }
@@ -224,15 +269,66 @@ export interface ToastOptions {
224
269
  message?: string;
225
270
  duration?: number;
226
271
  anchor?: "topRight" | "topLeft" | "bottomRight" | "bottomLeft" | string;
227
- size?: "md" | "lg" | "xl" | string;
272
+ size?: SizeNoSmall;
273
+ /**
274
+ * Icon name. Accepts either a full icon class (e.g. "icon-bell")
275
+ * or a bare name (e.g. "bell"), which will be prefixed with "icon-".
276
+ */
228
277
  icon?: string;
229
278
  }
230
279
 
280
+ export interface PageHeaderProps extends BaseProps {
281
+ title?: string;
282
+ description?: string;
283
+ trailing?: BunnixChildren | (() => BunnixChildren);
284
+ }
285
+
286
+ export interface PageSectionProps extends BaseProps {
287
+ title?: string;
288
+ stickyOffset?: string | number;
289
+ gap?: "small" | "regular" | "large" | string;
290
+ trailing?: BunnixChildren | (() => BunnixChildren);
291
+ }
292
+
293
+ export interface TableColumn {
294
+ field: string;
295
+ label: string;
296
+ size?: "auto" | number | string;
297
+ }
298
+
299
+ export interface TableSortableConfig {
300
+ field: string;
301
+ sortType?: "string" | "number" | "date";
302
+ sorted?: boolean;
303
+ direction?: "asc" | "desc";
304
+ }
305
+
306
+ export interface TableSearchableConfig {
307
+ field: string;
308
+ searchText?: string | any;
309
+ }
310
+
311
+ export interface TableProps extends BaseProps {
312
+ columns?: Array<TableColumn>;
313
+ data?: Array<any> | any;
314
+ key?: string;
315
+ renderCell?: (columnIndex: number, field: string, row: any, column?: TableColumn) => any;
316
+ cell?: (columnIndex: number, field: string, row: any, column?: TableColumn) => any;
317
+ searchable?: TableSearchableConfig;
318
+ sortable?: Array<TableSortableConfig>;
319
+ selection?: (keys: Array<string>) => void;
320
+ sort?: (field?: string) => ((a: any, b: any) => number) | null;
321
+ variant?: "regular" | "background" | "bordered" | string;
322
+ interactive?: boolean;
323
+ hideHeaders?: boolean;
324
+ }
325
+
231
326
  export type Component<P = BaseProps> = (props?: P, children?: BunnixChildren) => any;
232
327
 
233
328
  export const AccordionGroup: Component<BaseProps>;
234
329
  export const Badge: Component<BadgeProps>;
235
330
  export const Button: Component<ButtonProps>;
331
+ export const Card: Component<CardProps>;
236
332
  export const Checkbox: Component<CheckboxProps>;
237
333
  export const CodeBlock: Component<CodeBlockProps>;
238
334
  export const ComboBox: Component<ComboBoxProps>;
@@ -241,22 +337,22 @@ export const DatePicker: Component<DatePickerProps>;
241
337
  export const Dialog: Component<BaseProps>;
242
338
  export const DropdownMenu: Component<DropdownMenuProps>;
243
339
  export const Grid: Component<BaseProps>;
244
- export const HStack: Component<StackProps>;
340
+ export const HStack: Component<HStackProps>;
245
341
  export const Icon: Component<IconProps>;
246
342
  export const InputField: Component<InputFieldProps>;
247
343
  export const NavigationBar: Component<NavigationBarProps>;
248
- export const PageHeader: Component<BaseProps>;
249
- export const PageSection: Component<BaseProps>;
344
+ export const PageHeader: Component<PageHeaderProps>;
345
+ export const PageSection: Component<PageSectionProps>;
250
346
  export const PopoverMenu: Component<PopoverMenuProps>;
251
347
  export const RadioCheckbox: Component<RadioCheckboxProps>;
252
348
  export const SearchBox: Component<SearchBoxProps>;
253
349
  export const Sidebar: Component<SidebarProps>;
254
- export const Table: Component<BaseProps>;
350
+ export const Table: Component<TableProps>;
255
351
  export const Text: Component<TextProps>;
256
352
  export const TimePicker: Component<TimePickerProps>;
257
353
  export const ToastNotification: Component<BaseProps>;
258
354
  export const ToggleSwitch: Component<ToggleSwitchProps>;
259
- export const VStack: Component<StackProps>;
355
+ export const VStack: Component<VStackProps>;
260
356
 
261
357
  export const dialogState: any;
262
358
  export function showDialog(options?: ShowDialogOptions): void;
package/README.md CHANGED
@@ -98,10 +98,10 @@ You can compose your own UI using the same CSS utilities the components use:
98
98
 
99
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
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`
101
+ - Typography: `text-default|primary|secondary|tertiary|quaternary`, `text-accent`, `text-destructive`, `text-sm|base|lg|xl`, `text-mono`, `whitespace-nowrap`, `whitespace-pre-line`
102
102
  - Buttons: `btn`, `btn-flat`, `btn-outline`, `btn-destructive`, `btn-lg`, `btn-xl`, `btn-disabled`
103
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`
104
+ - Icons: `icon`, `icon-<name>`, `icon-xs|sm|lg|xl`, `icon-default|base|white|secondary|tertiary|quaternary`
105
105
 
106
106
  Example:
107
107
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bunnix/components",
3
- "version": "0.9.1",
3
+ "version": "0.9.2",
4
4
  "description": "Bunnix components: a set of bunnix ready components for modern web apps.",
5
5
  "keywords": [
6
6
  "bunnix",
@@ -1,4 +1,5 @@
1
1
  import Bunnix, { useState } from "@bunnix/core";
2
+ import { resolveIconClass } from "../utils/iconUtils.mjs";
2
3
  const { div, button, span, p } = Bunnix;
3
4
 
4
5
  export default function AccordionGroup({ items = [], class: className = "", initialIndex } = {}) {
@@ -16,7 +17,7 @@ export default function AccordionGroup({ items = [], class: className = "", init
16
17
  { class: `accordion-group ${className}`.trim() },
17
18
  items.map((item, index) => {
18
19
  const isOpen = openIndex.map((value) => value === index);
19
- const iconClass = item.icon ? item.icon : "icon-add";
20
+ const iconClass = resolveIconClass(item.icon) || "icon-add";
20
21
  const description = item.description ?? item.content ?? "";
21
22
 
22
23
  return div({ class: isOpen.map((open) => `accordion-item hoverable ${open ? "accordion-open" : ""}`) }, [
@@ -1,4 +1,5 @@
1
1
  import Bunnix from "@bunnix/core";
2
+ import { clampSize, toSizeToken } from "../utils/sizeUtils.mjs";
2
3
  import Icon from "./Icon.mjs";
3
4
 
4
5
  const { span } = Bunnix;
@@ -16,7 +17,9 @@ const toneClassMap = {
16
17
  const sizeClassMap = {
17
18
  xs: "badge-xs",
18
19
  sm: "badge-sm",
19
- md: "badge-md"
20
+ md: "badge-md",
21
+ lg: "badge-lg",
22
+ xl: "badge-xl"
20
23
  };
21
24
 
22
25
  const variantClassMap = {
@@ -27,17 +30,28 @@ const variantClassMap = {
27
30
 
28
31
  export default function Badge({
29
32
  tone = "base",
30
- size = "sm",
33
+ size = "small",
31
34
  variant = "solid",
32
35
  icon,
33
36
  overlap = false,
34
37
  shape = "capsule",
35
38
  class: className = ""
36
39
  } = {}, children) {
40
+ // Badge supports all sizes
41
+ const normalizeSize = (value) => clampSize(value, ["xsmall", "small", "regular", "large", "xlarge"], "small");
42
+ const normalizedSize = normalizeSize(size);
43
+ const sizeToken = toSizeToken(normalizedSize);
44
+
37
45
  const toneClass = toneClassMap[tone] || toneClassMap.base;
38
- const sizeClass = sizeClassMap[size] || sizeClassMap.sm;
46
+ const sizeClass = sizeClassMap[sizeToken] || sizeClassMap.sm;
39
47
  const variantClass = variantClassMap[variant] || variantClassMap.solid;
40
- const iconSize = size === "md" ? "lg" : size === "xs" ? "xs" : "sm";
48
+ const iconSize = normalizedSize === "regular"
49
+ ? "large"
50
+ : normalizedSize === "xsmall"
51
+ ? "xsmall"
52
+ : normalizedSize === "xlarge"
53
+ ? "xlarge"
54
+ : "small";
41
55
  const overlapClass = overlap ? "badge-overlap" : "";
42
56
  const shapeClass = shape === "circle" ? "badge-circle" : "";
43
57
  const combinedClass = `badge ${toneClass} ${sizeClass} ${variantClass} ${overlapClass} ${shapeClass} ${className}`.trim();
@@ -1,4 +1,5 @@
1
1
  import Bunnix from "@bunnix/core";
2
+ import { clampSize, toSizeToken } from "../utils/sizeUtils.mjs";
2
3
  const { button, a } = Bunnix;
3
4
 
4
5
  export default function Button({
@@ -12,12 +13,8 @@ export default function Button({
12
13
  class: className = "",
13
14
  ...rest
14
15
  } = {}, 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
- };
16
+ // Button supports all sizes
17
+ const normalizeSize = (value) => clampSize(value, ["xsmall", "small", "regular", "large", "xlarge"], "regular");
21
18
 
22
19
  const variantState = variant && typeof variant.map === "function" ? variant : null;
23
20
  const sizeState = size && typeof size.map === "function" ? size : null;
@@ -28,13 +25,14 @@ export default function Button({
28
25
 
29
26
  const buildClass = (variantValue, sizeValue, disabledValue) => {
30
27
  const normalizedSize = normalizeSize(sizeValue);
28
+ const sizeToken = toSizeToken(normalizedSize);
31
29
  const baseClass = isHyperlink ? "" : "btn";
32
30
  const variantClass = (isHyperlink || variantValue === "regular") ? "" : `btn-${variantValue}`;
33
- const sizeClass = (!isHyperlink && normalizedSize && normalizedSize !== "md" && (normalizedSize === "lg" || normalizedSize === "xl"))
34
- ? `btn-${normalizedSize}`
31
+ const sizeClass = (!isHyperlink && sizeToken && sizeToken !== "md")
32
+ ? `btn-${sizeToken}`
35
33
  : "";
36
34
  const disabledClass = disabledValue ? "btn-disabled" : "";
37
- return `${baseClass} ${variantClass} ${sizeClass} ${disabledClass} ${className}`.trim();
35
+ return `row-container justify-start shrink-0 no-selectable ${baseClass} ${variantClass} ${sizeClass} ${disabledClass} ${className}`.trim();
38
36
  };
39
37
 
40
38
  const combinedClass = variantState
@@ -0,0 +1,37 @@
1
+ import Bunnix from "@bunnix/core";
2
+
3
+ const { div } = Bunnix;
4
+
5
+ const directionClassMap = {
6
+ horizontal: "row-container",
7
+ vertical: "column-container"
8
+ };
9
+
10
+ export default function Card({
11
+ direction,
12
+ alignment,
13
+ class: className = "",
14
+ ...rest
15
+ } = {}, children) {
16
+ const directionClass = directionClassMap[direction] || "";
17
+ const rowAlignmentMap = {
18
+ leading: "justify-start",
19
+ middle: "justify-center",
20
+ trailing: "justify-end"
21
+ };
22
+ const columnAlignmentMap = {
23
+ leading: "items-start",
24
+ middle: "items-center",
25
+ trailing: "items-end"
26
+ };
27
+ const alignmentClass = alignment
28
+ ? direction === "vertical"
29
+ ? columnAlignmentMap[alignment] || ""
30
+ : direction === "horizontal"
31
+ ? rowAlignmentMap[alignment] || ""
32
+ : ""
33
+ : "";
34
+ const combinedClass = `card ${directionClass} ${alignmentClass} ${className}`.trim();
35
+
36
+ return div({ class: combinedClass, ...rest }, children);
37
+ }
@@ -1,4 +1,5 @@
1
1
  import Bunnix from "@bunnix/core";
2
+ import { clampSize, toSizeToken } from "../utils/sizeUtils.mjs";
2
3
  const { label, input, span } = Bunnix;
3
4
 
4
5
  export default function Checkbox({
@@ -10,14 +11,11 @@ export default function Checkbox({
10
11
  class: className = "",
11
12
  ...inputProps
12
13
  }) {
13
- const normalizeSize = (value) => {
14
- if (!value || value === "default" || value === "regular" || value === "md") return "md";
15
- if (value === "sm") return "sm";
16
- if (value === "lg" || value === "xl") return value;
17
- return value;
18
- };
14
+ // Checkbox supports all sizes
15
+ const normalizeSize = (value) => clampSize(value, ["xsmall", "small", "regular", "large", "xlarge"], "regular");
19
16
  const normalizedSize = normalizeSize(size);
20
- const sizeClass = normalizedSize === "lg" ? "checkbox-lg" : normalizedSize === "xl" ? "checkbox-xl" : "";
17
+ const sizeToken = toSizeToken(normalizedSize);
18
+ const sizeClass = sizeToken === "xl" ? "checkbox-xl" : sizeToken === "lg" ? "checkbox-lg" : "";
21
19
  const nativeChange = onChange ?? inputProps.change;
22
20
  const checkHandler = onCheck ?? check;
23
21
 
@@ -1,5 +1,6 @@
1
1
  import Bunnix from "@bunnix/core";
2
- const { select, option } = Bunnix;
2
+ import { clampSize, toSizeToken } from "../utils/sizeUtils.mjs";
3
+ const { select, option, div, span } = Bunnix;
3
4
 
4
5
  export default function ComboBox({
5
6
  options = [],
@@ -10,14 +11,18 @@ export default function ComboBox({
10
11
  change,
11
12
  ...rest
12
13
  } = {}, children) {
13
- const normalizeSize = (value) => {
14
- if (!value || value === "default" || value === "regular" || value === "md") return "md";
15
- if (value === "sm") return "sm";
16
- if (value === "lg" || value === "xl") return value;
17
- return value;
18
- };
14
+ // ComboBox supports all sizes
15
+ const normalizeSize = (value) => clampSize(value, ["xsmall", "small", "regular", "large", "xlarge"], "regular");
19
16
  const normalizedSize = normalizeSize(size);
20
- const sizeClass = normalizedSize === "lg" ? "input-lg" : normalizedSize === "xl" ? "input-xl" : "";
17
+ const sizeToken = toSizeToken(normalizedSize);
18
+ const sizeClass = sizeToken === "xl" ? "input-xl" : sizeToken === "lg" ? "input-lg" : "";
19
+ const iconSizeClass = sizeToken === "sm"
20
+ ? "icon-sm"
21
+ : sizeToken === "lg"
22
+ ? "icon-lg"
23
+ : sizeToken === "xl"
24
+ ? "icon-xl"
25
+ : "";
21
26
  const selectionState = selection && typeof selection.map === "function" ? selection : null;
22
27
  const handleChangeExternal = onChange ?? change;
23
28
 
@@ -35,10 +40,13 @@ export default function ComboBox({
35
40
  return option({ value: opt.value }, opt.label ?? opt.value);
36
41
  });
37
42
 
38
- return select({
39
- class: `${sizeClass} ${className}`.trim(),
40
- value: selection ?? "",
41
- change: handleChange,
42
- ...rest
43
- }, resolvedChildren);
43
+ return div({ class: "combobox" }, [
44
+ select({
45
+ class: `combobox-select ${sizeClass} ${className}`.trim(),
46
+ value: selection ?? "",
47
+ change: handleChange,
48
+ ...rest
49
+ }, resolvedChildren),
50
+ span({ class: `combobox-chevron icon icon-chevron-down icon-base ${iconSizeClass}`.trim() })
51
+ ]);
44
52
  }
@@ -5,23 +5,21 @@ const { div } = Bunnix;
5
5
  const typeClassMap = {
6
6
  main: "main-container",
7
7
  content: "main-content",
8
- page: "page-layout"
8
+ page: "page-layout",
9
9
  };
10
10
 
11
11
  const directionClassMap = {
12
- horizontal: "row-container",
13
- vertical: "column-container"
12
+ row: "row-container",
13
+ column: "column-container",
14
14
  };
15
15
 
16
- export default function Container({
17
- type,
18
- direction,
19
- class: className = "",
20
- ...rest
21
- } = {}, children) {
16
+ export default function Container(
17
+ { type = "box", direction = "column", class: className = "", ...rest } = {},
18
+ ...children
19
+ ) {
22
20
  const typeClass = typeClassMap[type] || "";
23
21
  const directionClass = directionClassMap[direction] || "";
24
22
  const combinedClass = `${typeClass} ${directionClass} ${className}`.trim();
25
23
 
26
- return div({ class: combinedClass, ...rest }, children);
24
+ return div({ class: combinedClass, ...rest }, ...children);
27
25
  }
@@ -1,4 +1,5 @@
1
1
  import Bunnix, { ForEach, useMemo, useRef, useState } from "@bunnix/core";
2
+ import { clampSize, toSizeToken } from "../utils/sizeUtils.mjs";
2
3
  import Icon from "./Icon.mjs";
3
4
  const { div, button, span, hr } = Bunnix;
4
5
 
@@ -51,7 +52,7 @@ export default function DatePicker({
51
52
  placeholder,
52
53
  range = false,
53
54
  variant = "regular",
54
- size = "md",
55
+ size = "regular",
55
56
  class: className = ""
56
57
  } = {}) {
57
58
  const popoverRef = useRef(null);
@@ -161,25 +162,22 @@ export default function DatePicker({
161
162
 
162
163
  const hasValue = inputValue.map(v => !!v);
163
164
 
164
- const normalizeSize = (value) => {
165
- if (!value || value === "default" || value === "regular" || value === "md") return "md";
166
- if (value === "sm") return "md";
167
- if (value === "lg" || value === "xl") return value;
168
- return value;
169
- };
165
+ // DatePicker does not support small size (clamps to regular)
166
+ const normalizeSize = (value) => clampSize(value, ["xsmall", "regular", "large", "xlarge"], "regular");
170
167
  const normalizedSize = normalizeSize(size);
168
+ const sizeToken = toSizeToken(normalizedSize);
171
169
  const variantClass = variant === "rounded" ? "rounded-full" : "";
172
- const triggerSizeClass = normalizedSize === "xl"
170
+ const triggerSizeClass = sizeToken === "xl"
173
171
  ? "dropdown-xl"
174
- : normalizedSize === "lg"
172
+ : sizeToken === "lg"
175
173
  ? "dropdown-lg"
176
174
  : "";
177
- const iconSizeValue = normalizedSize === "sm"
178
- ? "sm"
179
- : normalizedSize === "lg"
180
- ? "lg"
181
- : normalizedSize === "xl"
182
- ? "xl"
175
+ const iconSizeValue = normalizedSize === "small"
176
+ ? "small"
177
+ : normalizedSize === "large"
178
+ ? "large"
179
+ : normalizedSize === "xlarge"
180
+ ? "xlarge"
183
181
  : undefined;
184
182
 
185
183
  return div({ class: `datepicker-wrapper ${className}`.trim() }, [