@abydahana/aksara-ui 0.1.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.
Files changed (103) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +163 -0
  3. package/dist/aksara.css +33499 -0
  4. package/dist/aksara.d.ts +284 -0
  5. package/dist/aksara.esm.js +1604 -0
  6. package/dist/aksara.js +1608 -0
  7. package/dist/aksara.min.css +1 -0
  8. package/dist/aksara.min.js +1 -0
  9. package/dist/components/buttons/button-group.d.ts +10 -0
  10. package/dist/components/buttons/button-group.js +12 -0
  11. package/dist/components/buttons/button.d.ts +18 -0
  12. package/dist/components/buttons/button.js +28 -0
  13. package/dist/components/buttons/close-button.d.ts +9 -0
  14. package/dist/components/buttons/close-button.js +13 -0
  15. package/dist/components/buttons/index.d.ts +3 -0
  16. package/dist/components/buttons/index.js +3 -0
  17. package/dist/components/data/accordion.d.ts +17 -0
  18. package/dist/components/data/accordion.js +37 -0
  19. package/dist/components/data/avatar.d.ts +26 -0
  20. package/dist/components/data/avatar.js +64 -0
  21. package/dist/components/data/card.d.ts +39 -0
  22. package/dist/components/data/card.js +34 -0
  23. package/dist/components/data/carousel.d.ts +15 -0
  24. package/dist/components/data/carousel.js +47 -0
  25. package/dist/components/data/index.d.ts +7 -0
  26. package/dist/components/data/index.js +7 -0
  27. package/dist/components/data/list-group.d.ts +22 -0
  28. package/dist/components/data/list-group.js +30 -0
  29. package/dist/components/data/media-grid.d.ts +19 -0
  30. package/dist/components/data/media-grid.js +47 -0
  31. package/dist/components/data/table.d.ts +35 -0
  32. package/dist/components/data/table.js +30 -0
  33. package/dist/components/feedback/alert.d.ts +10 -0
  34. package/dist/components/feedback/alert.js +19 -0
  35. package/dist/components/feedback/badge.d.ts +13 -0
  36. package/dist/components/feedback/badge.js +10 -0
  37. package/dist/components/feedback/index.d.ts +6 -0
  38. package/dist/components/feedback/index.js +6 -0
  39. package/dist/components/feedback/placeholder.d.ts +9 -0
  40. package/dist/components/feedback/placeholder.js +11 -0
  41. package/dist/components/feedback/progress.d.ts +14 -0
  42. package/dist/components/feedback/progress.js +22 -0
  43. package/dist/components/feedback/spinner.d.ts +9 -0
  44. package/dist/components/feedback/spinner.js +12 -0
  45. package/dist/components/feedback/toast.d.ts +22 -0
  46. package/dist/components/feedback/toast.js +36 -0
  47. package/dist/components/form/checkbox.d.ts +17 -0
  48. package/dist/components/form/checkbox.js +29 -0
  49. package/dist/components/form/floating-label.d.ts +9 -0
  50. package/dist/components/form/floating-label.js +14 -0
  51. package/dist/components/form/form-control.d.ts +30 -0
  52. package/dist/components/form/form-control.js +28 -0
  53. package/dist/components/form/index.d.ts +11 -0
  54. package/dist/components/form/index.js +11 -0
  55. package/dist/components/form/input-group.d.ts +16 -0
  56. package/dist/components/form/input-group.js +14 -0
  57. package/dist/components/form/input.d.ts +18 -0
  58. package/dist/components/form/input.js +19 -0
  59. package/dist/components/form/layout.d.ts +20 -0
  60. package/dist/components/form/layout.js +15 -0
  61. package/dist/components/form/radio.d.ts +32 -0
  62. package/dist/components/form/radio.js +49 -0
  63. package/dist/components/form/range.d.ts +13 -0
  64. package/dist/components/form/range.js +18 -0
  65. package/dist/components/form/select.d.ts +25 -0
  66. package/dist/components/form/select.js +37 -0
  67. package/dist/components/form/switch.d.ts +16 -0
  68. package/dist/components/form/switch.js +30 -0
  69. package/dist/components/form/textarea.d.ts +17 -0
  70. package/dist/components/form/textarea.js +19 -0
  71. package/dist/components/index.d.ts +7 -0
  72. package/dist/components/index.js +7 -0
  73. package/dist/components/navigation/breadcrumb.d.ts +13 -0
  74. package/dist/components/navigation/breadcrumb.js +25 -0
  75. package/dist/components/navigation/index.d.ts +5 -0
  76. package/dist/components/navigation/index.js +5 -0
  77. package/dist/components/navigation/navbar.d.ts +20 -0
  78. package/dist/components/navigation/navbar.js +22 -0
  79. package/dist/components/navigation/pagination.d.ts +15 -0
  80. package/dist/components/navigation/pagination.js +31 -0
  81. package/dist/components/navigation/scrollspy.d.ts +23 -0
  82. package/dist/components/navigation/scrollspy.js +43 -0
  83. package/dist/components/navigation/tabs.d.ts +15 -0
  84. package/dist/components/navigation/tabs.js +56 -0
  85. package/dist/components/overlay/collapse.d.ts +20 -0
  86. package/dist/components/overlay/collapse.js +27 -0
  87. package/dist/components/overlay/dropdown.d.ts +33 -0
  88. package/dist/components/overlay/dropdown.js +41 -0
  89. package/dist/components/overlay/index.d.ts +7 -0
  90. package/dist/components/overlay/index.js +7 -0
  91. package/dist/components/overlay/media-modal.d.ts +15 -0
  92. package/dist/components/overlay/media-modal.js +83 -0
  93. package/dist/components/overlay/modal.d.ts +32 -0
  94. package/dist/components/overlay/modal.js +47 -0
  95. package/dist/components/overlay/offcanvas.d.ts +20 -0
  96. package/dist/components/overlay/offcanvas.js +33 -0
  97. package/dist/components/overlay/popover.d.ts +19 -0
  98. package/dist/components/overlay/popover.js +24 -0
  99. package/dist/components/overlay/tooltip.d.ts +17 -0
  100. package/dist/components/overlay/tooltip.js +21 -0
  101. package/dist/components/utils.d.ts +3 -0
  102. package/dist/components/utils.js +25 -0
  103. package/package.json +111 -0
@@ -0,0 +1,49 @@
1
+ import { classNames, escapeHtml, toAttributes } from "../utils";
2
+ export function Radio(props) {
3
+ const { label, name, id, value, checked = false, disabled = false, inline = false, isInvalid = false, isValid = false, className = "", inputClassName = "", labelClassName = "", attributes } = props;
4
+ const containerClasses = classNames("form-check", inline && "form-check-inline", className);
5
+ const inputClasses = classNames("form-check-input", isInvalid && "is-invalid", isValid && "is-valid", inputClassName);
6
+ const baseAttrs = toAttributes({
7
+ type: "radio",
8
+ name,
9
+ id,
10
+ value,
11
+ checked,
12
+ disabled,
13
+ ...attributes
14
+ });
15
+ const labelHtml = label
16
+ ? `
17
+ <label class="${classNames("form-check-label", labelClassName)}"${id ? ` for="${escapeHtml(id)}"` : ""}>
18
+ ${escapeHtml(label)}
19
+ </label>
20
+ `.trim()
21
+ : "";
22
+ return `
23
+ <div class="${containerClasses}">
24
+ <input class="${inputClasses}"${baseAttrs} />
25
+ ${labelHtml}
26
+ </div>
27
+ `.trim();
28
+ }
29
+ export const radio = Radio;
30
+ export function RadioGroup(props) {
31
+ const { name, options = [], value, inline = false, className = "" } = props;
32
+ const itemsHtml = options
33
+ .map((opt, idx) => {
34
+ const id = opt.id ?? `${name}-opt-${idx}`;
35
+ const isChecked = value !== undefined && String(opt.value) === String(value);
36
+ return Radio({
37
+ name,
38
+ id,
39
+ label: opt.label,
40
+ value: opt.value,
41
+ checked: isChecked,
42
+ disabled: opt.disabled,
43
+ inline
44
+ });
45
+ })
46
+ .join("\n");
47
+ return `<div class="${classNames("radio-group", className)}">${itemsHtml}</div>`.trim();
48
+ }
49
+ export const radioGroup = RadioGroup;
@@ -0,0 +1,13 @@
1
+ export interface RangeProps {
2
+ name?: string;
3
+ id?: string;
4
+ min?: number;
5
+ max?: number;
6
+ step?: number;
7
+ value?: number;
8
+ disabled?: boolean;
9
+ className?: string;
10
+ attributes?: Record<string, unknown>;
11
+ }
12
+ export declare function Range(props?: RangeProps): string;
13
+ export declare const range: typeof Range;
@@ -0,0 +1,18 @@
1
+ import { classNames, toAttributes } from "../utils";
2
+ export function Range(props = {}) {
3
+ const { name, id, min = 0, max = 100, step = 1, value, disabled = false, className = "", attributes } = props;
4
+ const classes = classNames("form-range", className);
5
+ const baseAttrs = toAttributes({
6
+ type: "range",
7
+ name,
8
+ id,
9
+ min,
10
+ max,
11
+ step,
12
+ value,
13
+ disabled,
14
+ ...attributes
15
+ });
16
+ return `<input class="${classes}"${baseAttrs} />`.trim();
17
+ }
18
+ export const range = Range;
@@ -0,0 +1,25 @@
1
+ export interface SelectOption {
2
+ label: string;
3
+ value: string | number;
4
+ disabled?: boolean;
5
+ }
6
+ export interface SelectOptGroup {
7
+ label: string;
8
+ options: SelectOption[];
9
+ }
10
+ export interface SelectProps {
11
+ name?: string;
12
+ id?: string;
13
+ options?: Array<SelectOption | SelectOptGroup>;
14
+ value?: string | number;
15
+ placeholder?: string;
16
+ disabled?: boolean;
17
+ required?: boolean;
18
+ size?: "sm" | "lg";
19
+ isInvalid?: boolean;
20
+ isValid?: boolean;
21
+ className?: string;
22
+ attributes?: Record<string, unknown>;
23
+ }
24
+ export declare function Select(props?: SelectProps): string;
25
+ export declare const select: typeof Select;
@@ -0,0 +1,37 @@
1
+ import { classNames, escapeHtml, toAttributes } from "../utils";
2
+ export function Select(props = {}) {
3
+ const { name, id, options = [], value, placeholder, disabled = false, required = false, size, isInvalid = false, isValid = false, className = "", attributes } = props;
4
+ const classes = classNames("form-select", size === "sm" && "form-select-sm", size === "lg" && "form-select-lg", isInvalid && "is-invalid", isValid && "is-valid", className);
5
+ const baseAttrs = toAttributes({
6
+ name,
7
+ id,
8
+ disabled,
9
+ required,
10
+ ...attributes
11
+ });
12
+ const placeholderHtml = placeholder
13
+ ? `<option value="" disabled${value === undefined || value === "" ? " selected" : ""}>${escapeHtml(placeholder)}</option>`
14
+ : "";
15
+ const renderOption = (opt) => {
16
+ const isSelected = value !== undefined && String(opt.value) === String(value);
17
+ const disabledAttr = opt.disabled ? " disabled" : "";
18
+ const selectedAttr = isSelected ? " selected" : "";
19
+ return `<option value="${escapeHtml(String(opt.value))}"${selectedAttr}${disabledAttr}>${escapeHtml(opt.label)}</option>`;
20
+ };
21
+ const optionsHtml = options
22
+ .map((item) => {
23
+ if ("options" in item) {
24
+ const groupOptions = item.options.map(renderOption).join("");
25
+ return `<optgroup label="${escapeHtml(item.label)}">${groupOptions}</optgroup>`;
26
+ }
27
+ return renderOption(item);
28
+ })
29
+ .join("");
30
+ return `
31
+ <select class="${classes}"${baseAttrs}>
32
+ ${placeholderHtml}
33
+ ${optionsHtml}
34
+ </select>
35
+ `.trim();
36
+ }
37
+ export const select = Select;
@@ -0,0 +1,16 @@
1
+ export interface SwitchProps {
2
+ label?: string;
3
+ name?: string;
4
+ id?: string;
5
+ checked?: boolean;
6
+ disabled?: boolean;
7
+ isInvalid?: boolean;
8
+ isValid?: boolean;
9
+ className?: string;
10
+ inputClassName?: string;
11
+ labelClassName?: string;
12
+ attributes?: Record<string, unknown>;
13
+ }
14
+ export declare function Switch(props?: SwitchProps): string;
15
+ export declare const switchInput: typeof Switch;
16
+ export declare const SwitchInput: typeof Switch;
@@ -0,0 +1,30 @@
1
+ import { classNames, escapeHtml, toAttributes } from "../utils";
2
+ export function Switch(props = {}) {
3
+ const { label, name, id, checked = false, disabled = false, isInvalid = false, isValid = false, className = "", inputClassName = "", labelClassName = "", attributes } = props;
4
+ const containerClasses = classNames("form-check form-switch", className);
5
+ const inputClasses = classNames("form-check-input", isInvalid && "is-invalid", isValid && "is-valid", inputClassName);
6
+ const baseAttrs = toAttributes({
7
+ type: "checkbox",
8
+ role: "switch",
9
+ name,
10
+ id,
11
+ checked,
12
+ disabled,
13
+ ...attributes
14
+ });
15
+ const labelHtml = label
16
+ ? `
17
+ <label class="${classNames("form-check-label", labelClassName)}"${id ? ` for="${escapeHtml(id)}"` : ""}>
18
+ ${escapeHtml(label)}
19
+ </label>
20
+ `.trim()
21
+ : "";
22
+ return `
23
+ <div class="${containerClasses}">
24
+ <input class="${inputClasses}"${baseAttrs} />
25
+ ${labelHtml}
26
+ </div>
27
+ `.trim();
28
+ }
29
+ export const switchInput = Switch;
30
+ export const SwitchInput = Switch;
@@ -0,0 +1,17 @@
1
+ export interface TextareaProps {
2
+ name?: string;
3
+ id?: string;
4
+ value?: string;
5
+ placeholder?: string;
6
+ rows?: number;
7
+ disabled?: boolean;
8
+ readOnly?: boolean;
9
+ required?: boolean;
10
+ isInvalid?: boolean;
11
+ isValid?: boolean;
12
+ className?: string;
13
+ autoGrow?: boolean;
14
+ attributes?: Record<string, unknown>;
15
+ }
16
+ export declare function Textarea(props?: TextareaProps): string;
17
+ export declare const textarea: typeof Textarea;
@@ -0,0 +1,19 @@
1
+ import { classNames, escapeHtml, toAttributes } from "../utils";
2
+ export function Textarea(props = {}) {
3
+ const { name, id, value = "", placeholder, rows = 3, disabled = false, readOnly = false, required = false, isInvalid = false, isValid = false, className = "", autoGrow = false, attributes } = props;
4
+ const isAutoGrow = autoGrow || rows === 1;
5
+ const classes = classNames("form-control", isAutoGrow && "form-control-autogrow", isInvalid && "is-invalid", isValid && "is-valid", className);
6
+ const baseAttrs = toAttributes({
7
+ name,
8
+ id,
9
+ placeholder,
10
+ rows,
11
+ disabled,
12
+ readonly: readOnly,
13
+ required,
14
+ ...(isAutoGrow ? { "data-role": "autogrow" } : {}),
15
+ ...attributes
16
+ });
17
+ return `<textarea class="${classes}"${baseAttrs}>${escapeHtml(value)}</textarea>`.trim();
18
+ }
19
+ export const textarea = Textarea;
@@ -0,0 +1,7 @@
1
+ export * from "./utils";
2
+ export * from "./form/index";
3
+ export * from "./data/index";
4
+ export * from "./feedback/index";
5
+ export * from "./overlay/index";
6
+ export * from "./navigation/index";
7
+ export * from "./buttons/index";
@@ -0,0 +1,7 @@
1
+ export * from "./utils";
2
+ export * from "./form/index";
3
+ export * from "./data/index";
4
+ export * from "./feedback/index";
5
+ export * from "./overlay/index";
6
+ export * from "./navigation/index";
7
+ export * from "./buttons/index";
@@ -0,0 +1,13 @@
1
+ export interface BreadcrumbItem {
2
+ label: string;
3
+ href?: string;
4
+ active?: boolean;
5
+ }
6
+ export interface BreadcrumbProps {
7
+ items: BreadcrumbItem[];
8
+ separator?: "slash" | "dot" | "arrow";
9
+ className?: string;
10
+ attributes?: Record<string, unknown>;
11
+ }
12
+ export declare function Breadcrumb(props: BreadcrumbProps): string;
13
+ export declare const breadcrumb: typeof Breadcrumb;
@@ -0,0 +1,25 @@
1
+ import { classNames, escapeHtml, toAttributes } from "../utils";
2
+ export function Breadcrumb(props) {
3
+ const { items = [], separator = "slash", className = "", attributes } = props;
4
+ const classes = classNames("breadcrumb", separator === "dot" && "breadcrumb-dot", separator === "arrow" && "breadcrumb-arrow", className);
5
+ const baseAttrs = toAttributes(attributes);
6
+ const renderedItems = items
7
+ .map((item, index) => {
8
+ const isLast = index === items.length - 1;
9
+ const isActive = item.active ?? isLast;
10
+ if (isActive) {
11
+ return `<li class="breadcrumb-item active" aria-current="page">${escapeHtml(item.label)}</li>`;
12
+ }
13
+ const href = item.href ?? "#";
14
+ return `<li class="breadcrumb-item"><a href="${escapeHtml(href)}">${escapeHtml(item.label)}</a></li>`;
15
+ })
16
+ .join("");
17
+ return `
18
+ <nav aria-label="breadcrumb"${baseAttrs}>
19
+ <ol class="${classes}">
20
+ ${renderedItems}
21
+ </ol>
22
+ </nav>
23
+ `.trim();
24
+ }
25
+ export const breadcrumb = Breadcrumb;
@@ -0,0 +1,5 @@
1
+ export * from "./navbar";
2
+ export * from "./breadcrumb";
3
+ export * from "./pagination";
4
+ export * from "./tabs";
5
+ export * from "./scrollspy";
@@ -0,0 +1,5 @@
1
+ export * from "./navbar";
2
+ export * from "./breadcrumb";
3
+ export * from "./pagination";
4
+ export * from "./tabs";
5
+ export * from "./scrollspy";
@@ -0,0 +1,20 @@
1
+ export interface NavbarProps {
2
+ children?: string;
3
+ brand?: string;
4
+ brandHref?: string;
5
+ expand?: "sm" | "md" | "lg" | "xl" | "xxl";
6
+ dark?: boolean;
7
+ className?: string;
8
+ attributes?: Record<string, unknown>;
9
+ }
10
+ export declare function Navbar(props?: NavbarProps): string;
11
+ export declare const navbar: typeof Navbar;
12
+ export interface NavLinkProps {
13
+ label: string;
14
+ href?: string;
15
+ active?: boolean;
16
+ disabled?: boolean;
17
+ className?: string;
18
+ }
19
+ export declare function NavLink(props: NavLinkProps): string;
20
+ export declare const navLink: typeof NavLink;
@@ -0,0 +1,22 @@
1
+ import { classNames, escapeHtml, toAttributes } from "../utils";
2
+ export function Navbar(props = {}) {
3
+ const { children = "", brand, brandHref = "#", expand, dark = false, className = "", attributes } = props;
4
+ const classes = classNames("navbar", expand ? `navbar-expand-${expand}` : "navbar-expand", dark && "navbar-dark bg-dark", className);
5
+ const baseAttrs = toAttributes(attributes);
6
+ const brandHtml = brand ? `<a class="navbar-brand" href="${escapeHtml(brandHref)}">${escapeHtml(brand)}</a>` : "";
7
+ return `
8
+ <nav class="${classes}"${baseAttrs}>
9
+ ${brandHtml}
10
+ ${children}
11
+ </nav>
12
+ `.trim();
13
+ }
14
+ export const navbar = Navbar;
15
+ export function NavLink(props) {
16
+ const { label, href = "#", active = false, disabled = false, className = "" } = props;
17
+ const classes = classNames("nav-link", active && "active", disabled && "disabled", className);
18
+ const currentAttr = active ? ' aria-current="page"' : "";
19
+ const disabledAttr = disabled ? ' tabindex="-1" aria-disabled="true"' : "";
20
+ return `<a class="${classes}" href="${escapeHtml(href)}"${currentAttr}${disabledAttr}>${escapeHtml(label)}</a>`.trim();
21
+ }
22
+ export const navLink = NavLink;
@@ -0,0 +1,15 @@
1
+ export interface PaginationItem {
2
+ label: string;
3
+ href?: string;
4
+ active?: boolean;
5
+ disabled?: boolean;
6
+ attributes?: Record<string, unknown>;
7
+ }
8
+ export interface PaginationProps {
9
+ items: PaginationItem[];
10
+ size?: "sm" | "lg";
11
+ className?: string;
12
+ attributes?: Record<string, unknown>;
13
+ }
14
+ export declare function Pagination(props: PaginationProps): string;
15
+ export declare const pagination: typeof Pagination;
@@ -0,0 +1,31 @@
1
+ import { classNames, escapeHtml, toAttributes } from "../utils";
2
+ export function Pagination(props) {
3
+ const { items = [], size, className = "", attributes } = props;
4
+ const classes = classNames("pagination", size === "sm" && "pagination-sm", size === "lg" && "pagination-lg", className);
5
+ const baseAttrs = toAttributes(attributes);
6
+ const renderedItems = items
7
+ .map((item) => {
8
+ const linkClasses = classNames("page-link", item.disabled && "disabled");
9
+ const liClasses = classNames("page-item", item.active && "active", item.disabled && "disabled");
10
+ const href = item.disabled ? "#" : (item.href ?? "#");
11
+ const currentAttr = item.active ? ' aria-current="page"' : "";
12
+ const disabledAttr = item.disabled ? ' aria-disabled="true" tabindex="-1"' : "";
13
+ const itemAttrs = toAttributes(item.attributes);
14
+ return `
15
+ <li class="${liClasses}">
16
+ <a href="${escapeHtml(href)}" class="${linkClasses}"${currentAttr}${disabledAttr}${itemAttrs}>
17
+ ${item.label}
18
+ </a>
19
+ </li>
20
+ `.trim();
21
+ })
22
+ .join("");
23
+ return `
24
+ <nav aria-label="Page navigation"${baseAttrs}>
25
+ <ul class="${classes}">
26
+ ${renderedItems}
27
+ </ul>
28
+ </nav>
29
+ `.trim();
30
+ }
31
+ export const pagination = Pagination;
@@ -0,0 +1,23 @@
1
+ export interface ScrollspyTargetProps {
2
+ id: string;
3
+ children?: string;
4
+ height?: string | number;
5
+ className?: string;
6
+ attributes?: Record<string, unknown>;
7
+ }
8
+ export declare function ScrollspyTarget(props: ScrollspyTargetProps): string;
9
+ export declare const scrollspyTarget: typeof ScrollspyTarget;
10
+ export interface ScrollspyNavItem {
11
+ id: string;
12
+ label: string;
13
+ active?: boolean;
14
+ }
15
+ export interface ScrollspyNavProps {
16
+ items: ScrollspyNavItem[];
17
+ targetId: string;
18
+ as?: "list-group" | "nav";
19
+ className?: string;
20
+ attributes?: Record<string, unknown>;
21
+ }
22
+ export declare function ScrollspyNav(props: ScrollspyNavProps): string;
23
+ export declare const scrollspyNav: typeof ScrollspyNav;
@@ -0,0 +1,43 @@
1
+ import { classNames, escapeHtml, toAttributes } from "../utils";
2
+ export function ScrollspyTarget(props) {
3
+ const { id, children = "", height = 300, className = "", attributes } = props;
4
+ const styleAttr = height
5
+ ? ` style="height: ${typeof height === "number" ? `${height}px` : height}; position: relative; overflow-y: auto;"`
6
+ : ' style="position: relative; overflow-y: auto;"';
7
+ const baseAttrs = toAttributes({
8
+ id,
9
+ "data-scrollspy": "target",
10
+ ...attributes
11
+ });
12
+ return `<div class="${classNames("scrollspy-target", className)}"${styleAttr}${baseAttrs}>${children}</div>`.trim();
13
+ }
14
+ export const scrollspyTarget = ScrollspyTarget;
15
+ export function ScrollspyNav(props) {
16
+ const { items = [], targetId, as = "list-group", className = "", attributes } = props;
17
+ const targetSelector = targetId.startsWith("#") ? targetId : `#${targetId}`;
18
+ const isListGroup = as === "list-group";
19
+ const containerClasses = classNames(isListGroup ? "list-group" : "nav flex-column", className);
20
+ const baseAttrs = toAttributes({
21
+ "data-scrollspy-nav": "true",
22
+ ...attributes
23
+ });
24
+ const linksHtml = items
25
+ .map((item, idx) => {
26
+ const isActive = item.active ?? idx === 0;
27
+ const linkClass = classNames(isListGroup ? "list-group-item list-group-item-action" : "nav-link", isActive && "active");
28
+ const sectionSelector = item.id.startsWith("#") ? item.id : `#${item.id}`;
29
+ return `
30
+ <a
31
+ href="${escapeHtml(sectionSelector)}"
32
+ class="${linkClass}"
33
+ data-scrollspy-link
34
+ data-scrollspy-container="${escapeHtml(targetSelector)}"
35
+ >
36
+ ${escapeHtml(item.label)}
37
+ </a>
38
+ `.trim();
39
+ })
40
+ .join("\n");
41
+ return `<nav class="${containerClasses}"${baseAttrs}>${linksHtml}</nav>`.trim();
42
+ }
43
+ export const scrollspyNav = ScrollspyNav;
@@ -0,0 +1,15 @@
1
+ export interface TabItem {
2
+ id: string;
3
+ label: string;
4
+ content: string;
5
+ active?: boolean;
6
+ disabled?: boolean;
7
+ }
8
+ export interface TabsProps {
9
+ items: TabItem[];
10
+ ariaLabel?: string;
11
+ className?: string;
12
+ attributes?: Record<string, unknown>;
13
+ }
14
+ export declare function Tabs(props: TabsProps): string;
15
+ export declare const tabs: typeof Tabs;
@@ -0,0 +1,56 @@
1
+ import { classNames, escapeHtml, toAttributes } from "../utils";
2
+ export function Tabs(props) {
3
+ const { items = [], ariaLabel = "Tabs", className = "", attributes } = props;
4
+ const hasActive = items.some((item) => item.active);
5
+ const activeIndex = hasActive ? items.findIndex((item) => item.active) : 0;
6
+ const buttonsHtml = items
7
+ .map((item, idx) => {
8
+ const isSelected = idx === activeIndex;
9
+ const btnClasses = classNames("tab", isSelected && "active", item.disabled && "disabled");
10
+ const disabledAttr = item.disabled ? " disabled" : "";
11
+ return `
12
+ <button
13
+ id="tab-${escapeHtml(item.id)}"
14
+ class="${btnClasses}"
15
+ type="button"
16
+ data-tabs="#panel-${escapeHtml(item.id)}"
17
+ role="tab"
18
+ aria-selected="${isSelected ? "true" : "false"}"
19
+ tabindex="${isSelected ? "0" : "-1"}"
20
+ aria-controls="panel-${escapeHtml(item.id)}"
21
+ ${disabledAttr}
22
+ >
23
+ ${escapeHtml(item.label)}
24
+ </button>
25
+ `.trim();
26
+ })
27
+ .join("");
28
+ const panelsHtml = items
29
+ .map((item, idx) => {
30
+ const isSelected = idx === activeIndex;
31
+ const hiddenAttr = isSelected ? "" : " hidden";
32
+ return `
33
+ <div
34
+ id="panel-${escapeHtml(item.id)}"
35
+ class="tab-panel"
36
+ role="tabpanel"
37
+ aria-labelledby="tab-${escapeHtml(item.id)}"${hiddenAttr}
38
+ >
39
+ ${item.content}
40
+ </div>
41
+ `.trim();
42
+ })
43
+ .join("\n");
44
+ const baseAttrs = toAttributes(attributes);
45
+ return `
46
+ <div class="${classNames("tabs-wrapper", className)}"${baseAttrs}>
47
+ <div class="tabs" role="tablist" aria-label="${escapeHtml(ariaLabel)}">
48
+ ${buttonsHtml}
49
+ </div>
50
+ <div class="tab-content mt-3">
51
+ ${panelsHtml}
52
+ </div>
53
+ </div>
54
+ `.trim();
55
+ }
56
+ export const tabs = Tabs;
@@ -0,0 +1,20 @@
1
+ export interface CollapseProps {
2
+ id: string;
3
+ children?: string;
4
+ show?: boolean;
5
+ horizontal?: boolean;
6
+ className?: string;
7
+ attributes?: Record<string, unknown>;
8
+ }
9
+ export declare function Collapse(props: CollapseProps): string;
10
+ export declare const collapse: typeof Collapse;
11
+ export interface CollapseTriggerProps {
12
+ targetId: string;
13
+ children: string;
14
+ as?: "button" | "a";
15
+ expanded?: boolean;
16
+ className?: string;
17
+ attributes?: Record<string, unknown>;
18
+ }
19
+ export declare function CollapseTrigger(props: CollapseTriggerProps): string;
20
+ export declare const collapseTrigger: typeof CollapseTrigger;
@@ -0,0 +1,27 @@
1
+ import { classNames, toAttributes } from "../utils";
2
+ export function Collapse(props) {
3
+ const { id, children = "", show = false, horizontal = false, className = "", attributes } = props;
4
+ const classes = classNames("collapse", show && "collapse-show show", horizontal && "collapse-horizontal", className);
5
+ const baseAttrs = toAttributes({
6
+ id,
7
+ ...attributes
8
+ });
9
+ return `<div class="${classes}"${baseAttrs}>${children}</div>`.trim();
10
+ }
11
+ export const collapse = Collapse;
12
+ export function CollapseTrigger(props) {
13
+ const { targetId, children, as: Tag = "button", expanded = false, className = "", attributes } = props;
14
+ const targetSelector = targetId.startsWith("#") ? targetId : `#${targetId}`;
15
+ const targetRawId = targetId.replace(/^#/, "");
16
+ const baseAttrs = toAttributes({
17
+ href: Tag === "a" ? targetSelector : undefined,
18
+ type: Tag === "button" ? "button" : undefined,
19
+ "data-collapse": targetSelector,
20
+ "data-collapse-target": targetSelector,
21
+ "aria-expanded": expanded ? "true" : "false",
22
+ "aria-controls": targetRawId,
23
+ ...attributes
24
+ });
25
+ return `<${Tag} class="${classNames(className)}"${baseAttrs}>${children}</${Tag}>`.trim();
26
+ }
27
+ export const collapseTrigger = CollapseTrigger;
@@ -0,0 +1,33 @@
1
+ export interface DropdownProps {
2
+ children?: string;
3
+ direction?: "up" | "end" | "start";
4
+ className?: string;
5
+ attributes?: Record<string, unknown>;
6
+ }
7
+ export declare function Dropdown(props?: DropdownProps): string;
8
+ export declare const dropdown: typeof Dropdown;
9
+ export interface DropdownMenuProps {
10
+ id?: string;
11
+ children?: string;
12
+ end?: boolean;
13
+ dark?: boolean;
14
+ className?: string;
15
+ attributes?: Record<string, unknown>;
16
+ }
17
+ export declare function DropdownMenu(props?: DropdownMenuProps): string;
18
+ export declare const dropdownMenu: typeof DropdownMenu;
19
+ export interface DropdownItemProps {
20
+ content?: string;
21
+ href?: string;
22
+ active?: boolean;
23
+ disabled?: boolean;
24
+ danger?: boolean;
25
+ className?: string;
26
+ attributes?: Record<string, unknown>;
27
+ }
28
+ export declare function DropdownItem(props?: DropdownItemProps): string;
29
+ export declare const dropdownItem: typeof DropdownItem;
30
+ export declare function DropdownDivider(className?: string): string;
31
+ export declare const dropdownDivider: typeof DropdownDivider;
32
+ export declare function DropdownHeader(title: string, className?: string): string;
33
+ export declare const dropdownHeader: typeof DropdownHeader;