@holmdigital/components 1.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.
- package/README.md +46 -0
- package/dist/Button/Button.js +117 -0
- package/dist/Button/Button.mjs +6 -0
- package/dist/Checkbox/Checkbox.js +82 -0
- package/dist/Checkbox/Checkbox.mjs +6 -0
- package/dist/Dialog/Dialog.js +129 -0
- package/dist/Dialog/Dialog.mjs +6 -0
- package/dist/FormField/FormField.js +110 -0
- package/dist/FormField/FormField.mjs +6 -0
- package/dist/Heading/Heading.js +48 -0
- package/dist/Heading/Heading.mjs +6 -0
- package/dist/Modal/Modal.js +146 -0
- package/dist/Modal/Modal.mjs +7 -0
- package/dist/NavigationMenu/NavigationMenu.js +141 -0
- package/dist/NavigationMenu/NavigationMenu.mjs +6 -0
- package/dist/RadioGroup/RadioGroup.js +103 -0
- package/dist/RadioGroup/RadioGroup.mjs +6 -0
- package/dist/Select/Select.js +157 -0
- package/dist/Select/Select.mjs +12 -0
- package/dist/SkipLink/SkipLink.js +59 -0
- package/dist/SkipLink/SkipLink.mjs +6 -0
- package/dist/Switch/Switch.js +82 -0
- package/dist/Switch/Switch.mjs +6 -0
- package/dist/Toast/Toast.js +123 -0
- package/dist/Toast/Toast.mjs +8 -0
- package/dist/Tooltip/Tooltip.js +121 -0
- package/dist/Tooltip/Tooltip.mjs +12 -0
- package/dist/chunk-2MJRKHPL.mjs +98 -0
- package/dist/chunk-5RKBS475.mjs +58 -0
- package/dist/chunk-C5M6C7KT.mjs +84 -0
- package/dist/chunk-GK4BYT56.mjs +117 -0
- package/dist/chunk-HALLFO25.mjs +22 -0
- package/dist/chunk-LZ42XDDI.mjs +105 -0
- package/dist/chunk-MKKQLWGK.mjs +35 -0
- package/dist/chunk-NDYRGXQ6.mjs +93 -0
- package/dist/chunk-NOE5QKC2.mjs +58 -0
- package/dist/chunk-PLT5CAFO.mjs +86 -0
- package/dist/chunk-V2JYAFB7.mjs +130 -0
- package/dist/chunk-W4ZHBRFT.mjs +14 -0
- package/dist/chunk-YMSNGQN6.mjs +79 -0
- package/dist/index.js +1256 -0
- package/dist/index.mjs +308 -0
- package/package.json +113 -0
package/README.md
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# @holmdigital/components
|
|
2
|
+
|
|
3
|
+
> Prescriptive, accessible React components for regulatory compliance.
|
|
4
|
+
|
|
5
|
+
These components are built to automatically solve common accessibility challenges found in regulatory audits. Using them ensures compliance "by default" for many WCAG criteria.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @holmdigital/components
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Usage
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { Button, FormField, Heading } from '@holmdigital/components';
|
|
17
|
+
|
|
18
|
+
function App() {
|
|
19
|
+
return (
|
|
20
|
+
<form>
|
|
21
|
+
<Heading level={1}>Contact Us</Heading>
|
|
22
|
+
<FormField
|
|
23
|
+
label="Email Address"
|
|
24
|
+
type="email"
|
|
25
|
+
required
|
|
26
|
+
autoComplete="email"
|
|
27
|
+
helpText="We'll never share your email."
|
|
28
|
+
/>
|
|
29
|
+
|
|
30
|
+
<Button variant="primary" type="submit">
|
|
31
|
+
Submit
|
|
32
|
+
</Button>
|
|
33
|
+
</form>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Compliance Features
|
|
39
|
+
|
|
40
|
+
- **High Contrast**: Default styles meet WCAG AA requirements.
|
|
41
|
+
- **Keyboard Navigation**: Full focus management and visible focus indicators.
|
|
42
|
+
- **Screen Reader Support**: Correct ARIA attributes and labels built-in.
|
|
43
|
+
|
|
44
|
+
## License
|
|
45
|
+
|
|
46
|
+
MIT © Holm Digital AB
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/Button/Button.tsx
|
|
21
|
+
var Button_exports = {};
|
|
22
|
+
__export(Button_exports, {
|
|
23
|
+
Button: () => Button
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(Button_exports);
|
|
26
|
+
var import_react = require("react");
|
|
27
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
28
|
+
var Button = (0, import_react.forwardRef)(
|
|
29
|
+
({
|
|
30
|
+
children,
|
|
31
|
+
variant = "primary",
|
|
32
|
+
size = "medium",
|
|
33
|
+
isLoading,
|
|
34
|
+
disabled,
|
|
35
|
+
className = "",
|
|
36
|
+
...props
|
|
37
|
+
}, ref) => {
|
|
38
|
+
const baseStyles = {
|
|
39
|
+
display: "inline-flex",
|
|
40
|
+
alignItems: "center",
|
|
41
|
+
justifyContent: "center",
|
|
42
|
+
borderRadius: "4px",
|
|
43
|
+
border: "none",
|
|
44
|
+
cursor: disabled || isLoading ? "not-allowed" : "pointer",
|
|
45
|
+
fontFamily: "inherit",
|
|
46
|
+
fontWeight: "600",
|
|
47
|
+
transition: "all 0.2s ease",
|
|
48
|
+
// Garantera synlig fokusindikator (WCAG 2.4.7)
|
|
49
|
+
outlineOffset: "2px"
|
|
50
|
+
};
|
|
51
|
+
const variants = {
|
|
52
|
+
primary: {
|
|
53
|
+
background: "#0056b3",
|
|
54
|
+
// AA Large, AAA Normal mot vit text
|
|
55
|
+
color: "#ffffff"
|
|
56
|
+
},
|
|
57
|
+
secondary: {
|
|
58
|
+
background: "#f8f9fa",
|
|
59
|
+
color: "#212529",
|
|
60
|
+
border: "1px solid #dee2e6"
|
|
61
|
+
},
|
|
62
|
+
danger: {
|
|
63
|
+
background: "#dc3545",
|
|
64
|
+
color: "#ffffff"
|
|
65
|
+
},
|
|
66
|
+
ghost: {
|
|
67
|
+
background: "transparent",
|
|
68
|
+
color: "#0056b3"
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
const sizes = {
|
|
72
|
+
small: {
|
|
73
|
+
padding: "0.25rem 0.5rem",
|
|
74
|
+
fontSize: "0.875rem",
|
|
75
|
+
minHeight: "32px"
|
|
76
|
+
// OBS: Kan bryta mot 44px om inte hanteras med margin
|
|
77
|
+
},
|
|
78
|
+
medium: {
|
|
79
|
+
padding: "0.5rem 1rem",
|
|
80
|
+
fontSize: "1rem",
|
|
81
|
+
minHeight: "44px"
|
|
82
|
+
// Touch target safe
|
|
83
|
+
},
|
|
84
|
+
large: {
|
|
85
|
+
padding: "0.75rem 1.5rem",
|
|
86
|
+
fontSize: "1.25rem",
|
|
87
|
+
minHeight: "56px"
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
const style = {
|
|
91
|
+
...baseStyles,
|
|
92
|
+
...variants[variant],
|
|
93
|
+
...sizes[size],
|
|
94
|
+
opacity: disabled || isLoading ? 0.65 : 1
|
|
95
|
+
};
|
|
96
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
97
|
+
"button",
|
|
98
|
+
{
|
|
99
|
+
ref,
|
|
100
|
+
style,
|
|
101
|
+
disabled: disabled || isLoading,
|
|
102
|
+
"aria-busy": isLoading,
|
|
103
|
+
tabIndex: props.tabIndex,
|
|
104
|
+
...props,
|
|
105
|
+
children: [
|
|
106
|
+
isLoading ? /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { "aria-hidden": "true", style: { marginRight: "8px" }, children: "\u23F3" }) : null,
|
|
107
|
+
children
|
|
108
|
+
]
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
}
|
|
112
|
+
);
|
|
113
|
+
Button.displayName = "Button";
|
|
114
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
115
|
+
0 && (module.exports = {
|
|
116
|
+
Button
|
|
117
|
+
});
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/Checkbox/Checkbox.tsx
|
|
21
|
+
var Checkbox_exports = {};
|
|
22
|
+
__export(Checkbox_exports, {
|
|
23
|
+
Checkbox: () => Checkbox
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(Checkbox_exports);
|
|
26
|
+
var import_react = require("react");
|
|
27
|
+
var import_lucide_react = require("lucide-react");
|
|
28
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
29
|
+
var Checkbox = (0, import_react.forwardRef)(
|
|
30
|
+
({ className = "", checked, onCheckedChange, onChange, label, disabled, id, ...props }, ref) => {
|
|
31
|
+
const handleChange = (e) => {
|
|
32
|
+
onCheckedChange?.(e.target.checked);
|
|
33
|
+
onChange?.(e);
|
|
34
|
+
};
|
|
35
|
+
const generatedId = id || `checkbox-${Math.random().toString(36).substr(2, 9)}`;
|
|
36
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: `flex items-start ${className}`, children: [
|
|
37
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex items-center h-5", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "relative", children: [
|
|
38
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
39
|
+
"input",
|
|
40
|
+
{
|
|
41
|
+
id: generatedId,
|
|
42
|
+
type: "checkbox",
|
|
43
|
+
ref,
|
|
44
|
+
className: "peer sr-only",
|
|
45
|
+
checked,
|
|
46
|
+
onChange: handleChange,
|
|
47
|
+
disabled,
|
|
48
|
+
...props
|
|
49
|
+
}
|
|
50
|
+
),
|
|
51
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
52
|
+
"div",
|
|
53
|
+
{
|
|
54
|
+
className: `
|
|
55
|
+
h-5 w-5 rounded border border-slate-300 bg-white shadow-sm transition-all
|
|
56
|
+
peer-focus:ring-2 peer-focus:ring-primary-500 peer-focus:ring-offset-2
|
|
57
|
+
peer-checked:bg-primary-600 peer-checked:border-primary-600
|
|
58
|
+
peer-disabled:cursor-not-allowed peer-disabled:opacity-50
|
|
59
|
+
hover:border-primary-400
|
|
60
|
+
flex items-center justify-center
|
|
61
|
+
`,
|
|
62
|
+
"aria-hidden": "true",
|
|
63
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.Check, { className: `h-3.5 w-3.5 text-white transition-opacity ${checked ? "opacity-100" : "opacity-0"}`, strokeWidth: 3 })
|
|
64
|
+
}
|
|
65
|
+
)
|
|
66
|
+
] }) }),
|
|
67
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
68
|
+
"label",
|
|
69
|
+
{
|
|
70
|
+
htmlFor: generatedId,
|
|
71
|
+
className: `ml-3 text-sm font-medium ${disabled ? "text-slate-400" : "text-slate-700"} cursor-pointer select-none`,
|
|
72
|
+
children: label
|
|
73
|
+
}
|
|
74
|
+
)
|
|
75
|
+
] });
|
|
76
|
+
}
|
|
77
|
+
);
|
|
78
|
+
Checkbox.displayName = "Checkbox";
|
|
79
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
80
|
+
0 && (module.exports = {
|
|
81
|
+
Checkbox
|
|
82
|
+
});
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/Dialog/Dialog.tsx
|
|
21
|
+
var Dialog_exports = {};
|
|
22
|
+
__export(Dialog_exports, {
|
|
23
|
+
Dialog: () => Dialog
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(Dialog_exports);
|
|
26
|
+
var import_react = require("react");
|
|
27
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
28
|
+
var CloseIcon = () => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
29
|
+
"svg",
|
|
30
|
+
{
|
|
31
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
32
|
+
width: "24",
|
|
33
|
+
height: "24",
|
|
34
|
+
viewBox: "0 0 24 24",
|
|
35
|
+
fill: "none",
|
|
36
|
+
stroke: "currentColor",
|
|
37
|
+
strokeWidth: "2",
|
|
38
|
+
strokeLinecap: "round",
|
|
39
|
+
strokeLinejoin: "round",
|
|
40
|
+
className: "h-5 w-5",
|
|
41
|
+
children: [
|
|
42
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M18 6 6 18" }),
|
|
43
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "m6 6 12 12" })
|
|
44
|
+
]
|
|
45
|
+
}
|
|
46
|
+
);
|
|
47
|
+
var Dialog = (0, import_react.forwardRef)(
|
|
48
|
+
({ isOpen, onClose, title, children, variant = "default", description, className, ...props }, ref) => {
|
|
49
|
+
const dialogRef = (0, import_react.useRef)(null);
|
|
50
|
+
(0, import_react.useImperativeHandle)(ref, () => dialogRef.current);
|
|
51
|
+
(0, import_react.useEffect)(() => {
|
|
52
|
+
const dialog = dialogRef.current;
|
|
53
|
+
if (!dialog) return;
|
|
54
|
+
if (isOpen) {
|
|
55
|
+
if (!dialog.open) {
|
|
56
|
+
dialog.showModal();
|
|
57
|
+
document.body.style.overflow = "hidden";
|
|
58
|
+
}
|
|
59
|
+
} else {
|
|
60
|
+
if (dialog.open) {
|
|
61
|
+
dialog.close();
|
|
62
|
+
document.body.style.overflow = "";
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}, [isOpen]);
|
|
66
|
+
(0, import_react.useEffect)(() => {
|
|
67
|
+
const dialog = dialogRef.current;
|
|
68
|
+
if (!dialog) return;
|
|
69
|
+
const handleClose = () => {
|
|
70
|
+
onClose();
|
|
71
|
+
document.body.style.overflow = "";
|
|
72
|
+
};
|
|
73
|
+
dialog.addEventListener("close", handleClose);
|
|
74
|
+
const handleBackdropClick = (e) => {
|
|
75
|
+
const rect = dialog.getBoundingClientRect();
|
|
76
|
+
const isInDialog = rect.top <= e.clientY && e.clientY <= rect.top + rect.height && rect.left <= e.clientX && e.clientX <= rect.left + rect.width;
|
|
77
|
+
if (!isInDialog) {
|
|
78
|
+
dialog.close();
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
dialog.addEventListener("click", handleBackdropClick);
|
|
82
|
+
return () => {
|
|
83
|
+
dialog.removeEventListener("close", handleClose);
|
|
84
|
+
dialog.removeEventListener("click", handleBackdropClick);
|
|
85
|
+
};
|
|
86
|
+
}, [onClose]);
|
|
87
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
|
|
88
|
+
"dialog",
|
|
89
|
+
{
|
|
90
|
+
ref: dialogRef,
|
|
91
|
+
className: `
|
|
92
|
+
backdrop:bg-slate-900/50 backdrop:backdrop-blur-sm
|
|
93
|
+
open:animate-in open:fade-in-0 open:zoom-in-95
|
|
94
|
+
bg-white rounded-xl shadow-2xl ring-1 ring-slate-900/5
|
|
95
|
+
w-full max-w-lg p-0
|
|
96
|
+
${className || ""}
|
|
97
|
+
`,
|
|
98
|
+
"aria-labelledby": "dialog-title",
|
|
99
|
+
"aria-describedby": description ? "dialog-desc" : void 0,
|
|
100
|
+
...props,
|
|
101
|
+
children: [
|
|
102
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center justify-between px-6 py-4 border-b border-slate-100", children: [
|
|
103
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("h2", { id: "dialog-title", className: `text-lg font-semibold ${variant === "alert" ? "text-red-600" : "text-slate-900"}`, children: title }),
|
|
104
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
105
|
+
"button",
|
|
106
|
+
{
|
|
107
|
+
onClick: () => {
|
|
108
|
+
dialogRef.current?.close();
|
|
109
|
+
},
|
|
110
|
+
className: "p-1 rounded-md text-slate-400 hover:text-slate-500 hover:bg-slate-100 focus:outline-none focus:ring-2 focus:ring-primary-500 transition-colors",
|
|
111
|
+
"aria-label": "Close dialog",
|
|
112
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(CloseIcon, {})
|
|
113
|
+
}
|
|
114
|
+
)
|
|
115
|
+
] }),
|
|
116
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "px-6 py-4", children: [
|
|
117
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { id: "dialog-desc", className: "text-sm text-slate-500 mb-4", children: description }),
|
|
118
|
+
children
|
|
119
|
+
] })
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
);
|
|
125
|
+
Dialog.displayName = "Dialog";
|
|
126
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
127
|
+
0 && (module.exports = {
|
|
128
|
+
Dialog
|
|
129
|
+
});
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/FormField/FormField.tsx
|
|
21
|
+
var FormField_exports = {};
|
|
22
|
+
__export(FormField_exports, {
|
|
23
|
+
FormField: () => FormField
|
|
24
|
+
});
|
|
25
|
+
module.exports = __toCommonJS(FormField_exports);
|
|
26
|
+
var import_react = require("react");
|
|
27
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
28
|
+
var FormField = (0, import_react.forwardRef)(
|
|
29
|
+
({
|
|
30
|
+
label,
|
|
31
|
+
error,
|
|
32
|
+
helpText,
|
|
33
|
+
required,
|
|
34
|
+
id,
|
|
35
|
+
className = "",
|
|
36
|
+
style,
|
|
37
|
+
...props
|
|
38
|
+
}, ref) => {
|
|
39
|
+
const generatedId = (0, import_react.useId)();
|
|
40
|
+
const inputId = id || `input-${generatedId}`;
|
|
41
|
+
const helpTextId = `help-${generatedId}`;
|
|
42
|
+
const errorId = `error-${generatedId}`;
|
|
43
|
+
const describedBy = [
|
|
44
|
+
helpText ? helpTextId : null,
|
|
45
|
+
error ? errorId : null
|
|
46
|
+
].filter(Boolean).join(" ");
|
|
47
|
+
const containerStyle = {
|
|
48
|
+
display: "flex",
|
|
49
|
+
flexDirection: "column",
|
|
50
|
+
marginBottom: "1rem",
|
|
51
|
+
fontFamily: "system-ui, sans-serif",
|
|
52
|
+
...style
|
|
53
|
+
};
|
|
54
|
+
const labelStyle = {
|
|
55
|
+
marginBottom: "0.5rem",
|
|
56
|
+
fontWeight: "600",
|
|
57
|
+
color: "#333"
|
|
58
|
+
};
|
|
59
|
+
const inputStyle = {
|
|
60
|
+
padding: "0.5rem",
|
|
61
|
+
borderRadius: "4px",
|
|
62
|
+
border: error ? "2px solid #dc3545" : "1px solid #ced4da",
|
|
63
|
+
fontSize: "1rem",
|
|
64
|
+
minHeight: "44px"
|
|
65
|
+
// Touch target
|
|
66
|
+
};
|
|
67
|
+
const errorStyle = {
|
|
68
|
+
color: "#dc3545",
|
|
69
|
+
fontSize: "0.875rem",
|
|
70
|
+
marginTop: "0.25rem",
|
|
71
|
+
display: "flex",
|
|
72
|
+
alignItems: "center"
|
|
73
|
+
};
|
|
74
|
+
const helpStyle = {
|
|
75
|
+
color: "#6c757d",
|
|
76
|
+
fontSize: "0.875rem",
|
|
77
|
+
marginTop: "0.25rem"
|
|
78
|
+
};
|
|
79
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: containerStyle, className, children: [
|
|
80
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("label", { htmlFor: inputId, style: labelStyle, children: [
|
|
81
|
+
label,
|
|
82
|
+
required && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { "aria-hidden": "true", style: { color: "#dc3545", marginLeft: "4px" }, children: "*" }),
|
|
83
|
+
required && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "sr-only", children: " (obligatoriskt)" })
|
|
84
|
+
] }),
|
|
85
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
86
|
+
"input",
|
|
87
|
+
{
|
|
88
|
+
ref,
|
|
89
|
+
id: inputId,
|
|
90
|
+
"aria-invalid": !!error,
|
|
91
|
+
"aria-describedby": describedBy || void 0,
|
|
92
|
+
"aria-required": required,
|
|
93
|
+
required,
|
|
94
|
+
style: inputStyle,
|
|
95
|
+
...props
|
|
96
|
+
}
|
|
97
|
+
),
|
|
98
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { id: errorId, style: errorStyle, role: "alert", children: [
|
|
99
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { "aria-hidden": "true", style: { marginRight: "4px" }, children: "\u26A0\uFE0F" }),
|
|
100
|
+
error
|
|
101
|
+
] }),
|
|
102
|
+
helpText && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { id: helpTextId, style: helpStyle, children: helpText })
|
|
103
|
+
] });
|
|
104
|
+
}
|
|
105
|
+
);
|
|
106
|
+
FormField.displayName = "FormField";
|
|
107
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
108
|
+
0 && (module.exports = {
|
|
109
|
+
FormField
|
|
110
|
+
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
|
|
30
|
+
// src/Heading/Heading.tsx
|
|
31
|
+
var Heading_exports = {};
|
|
32
|
+
__export(Heading_exports, {
|
|
33
|
+
Heading: () => Heading
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(Heading_exports);
|
|
36
|
+
var import_react = __toESM(require("react"));
|
|
37
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
38
|
+
var Heading = import_react.default.forwardRef(
|
|
39
|
+
({ level, children, className, ...props }, ref) => {
|
|
40
|
+
const Tag = `h${level}`;
|
|
41
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Tag, { ref, className, ...props, children });
|
|
42
|
+
}
|
|
43
|
+
);
|
|
44
|
+
Heading.displayName = "Heading";
|
|
45
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
46
|
+
0 && (module.exports = {
|
|
47
|
+
Heading
|
|
48
|
+
});
|