@obosbbl/grunnmuren-react 1.7.0 → 1.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.
@@ -6,4 +6,5 @@ export declare const RadioContext: import("react").Context<{
6
6
  onChange?(event: React.ChangeEvent<HTMLInputElement>): void;
7
7
  required?: boolean | undefined;
8
8
  value?: string | undefined;
9
+ error?: boolean | undefined;
9
10
  }>;
@@ -4,6 +4,8 @@ export interface RadioGroupProps extends Omit<React.ComponentPropsWithoutRef<'di
4
4
  defaultValue?: string;
5
5
  /** Help text for the radio group. */
6
6
  description?: React.ReactNode;
7
+ /** Error message for the form control */
8
+ error?: string;
7
9
  /** The `name` attribute for the radio buttons. */
8
10
  name: string;
9
11
  /** The label for the radio group. */
@@ -1,7 +1,21 @@
1
1
  /// <reference types="react" />
2
- export interface SelectProps extends React.ComponentPropsWithoutRef<'select'> {
2
+ export interface SelectProps extends Omit<React.ComponentPropsWithoutRef<'select'>, 'size'> {
3
+ /**
4
+ * Collection of <option />-elements
5
+ */
3
6
  children: React.ReactNode;
4
- id?: string;
5
- className?: string;
7
+ /** Help text for the form control */
8
+ description?: React.ReactNode;
9
+ /** Disables the built in HTML5 validation. If using custom validation for an entire form, consider setting `noValidate` on the form element instead. @default false */
10
+ disableValidation?: boolean;
11
+ /** Error message for the form control */
12
+ error?: string;
13
+ /** Label for the form control */
14
+ label: string;
15
+ /**
16
+ * Changes font-size, padding and gaps
17
+ * @default medium
18
+ */
19
+ size?: 'medium' | 'small';
6
20
  }
7
21
  export declare const Select: import("react").ForwardRefExoticComponent<SelectProps & import("react").RefAttributes<HTMLSelectElement>>;
@@ -0,0 +1,15 @@
1
+ /// <reference types="react" />
2
+ export interface SelectPlainProps extends Omit<React.ComponentPropsWithoutRef<'select'>, 'size'> {
3
+ /**
4
+ * Collection of <option />-elements
5
+ */
6
+ children: React.ReactNode;
7
+ /** Render select as invalid. Sets `aria-invalid` to true */
8
+ isInvalid?: boolean;
9
+ /**
10
+ * Changes font-size, padding and gaps
11
+ * @default medium
12
+ */
13
+ size?: 'medium' | 'small';
14
+ }
15
+ export declare const SelectPlain: import("react").ForwardRefExoticComponent<SelectPlainProps & import("react").RefAttributes<HTMLSelectElement>>;
@@ -633,10 +633,10 @@ const Checkbox = forwardRef((props, ref) => {
633
633
  return /* @__PURE__ */ jsxs("div", {
634
634
  className: "grid gap-2",
635
635
  children: [/* @__PURE__ */ jsxs("label", {
636
- className: cx(className, "inline-flex cursor-pointer items-center"),
636
+ className: cx(className, "flex cursor-pointer gap-2.5"),
637
637
  children: [/* @__PURE__ */ jsx("input", __spreadProps(__spreadValues({
638
638
  id,
639
- className: cx("checkbox checked:bg-green checked:border-green mr-3 grid h-[1.25em] w-[1.25em] flex-none cursor-pointer appearance-none place-content-center rounded border-2 border-solid bg-white text-white focus:outline-none focus:ring-2", {
639
+ className: cx("checkbox checked:bg-green checked:border-green grid h-[1.25em] w-[1.25em] flex-none translate-y-[0.1em] cursor-pointer appearance-none place-content-center rounded border-2 border-solid bg-white text-white focus:outline-none focus:ring-2", {
640
640
  "border-gray-dark focus:ring-black": !error,
641
641
  "border-red focus:ring-red": !!error
642
642
  }),
@@ -760,7 +760,7 @@ const FormErrorMessage = (props) => {
760
760
  "className"
761
761
  ]);
762
762
  return /* @__PURE__ */ jsxs("div", __spreadProps(__spreadValues({
763
- className: cx(className, "bg-red-light text-red flex items-center gap-2 rounded-lg py-1 px-4 text-sm"),
763
+ className: cx(className, "bg-red-light text-red flex items-center gap-2 rounded py-1 px-2 text-sm"),
764
764
  "aria-live": "polite"
765
765
  }, rest), {
766
766
  children: [/* @__PURE__ */ jsx(Warning, {
@@ -985,7 +985,7 @@ const Input = forwardRef((props, ref) => {
985
985
  const Component = as != null ? as : "input";
986
986
  const type = getType(Component, typeProp);
987
987
  return /* @__PURE__ */ jsxs("div", {
988
- className: cx(className, "relative flex items-center rounded-md border-[1px] border-b-[3px] focus-within:-ml-[2px] focus-within:-mt-[2px] focus-within:border-[3px] focus-within:shadow", {
988
+ className: cx(className, "relative flex items-center rounded-lg border border-b-[3px] focus-within:-ml-[2px] focus-within:-mt-[2px] focus-within:border-[3px] focus-within:shadow", {
989
989
  "focus-within:border-blue-dark border-black": !isInvalid,
990
990
  "border-red focus-within:border-red": isInvalid,
991
991
  "w-fit": size != null,
@@ -996,7 +996,7 @@ const Input = forwardRef((props, ref) => {
996
996
  children: [leftAddon, /* @__PURE__ */ jsx(Component, __spreadValues({
997
997
  "aria-invalid": isInvalid,
998
998
  ref,
999
- className: "focus:none placeholder-gray w-full rounded-md border-none px-4 py-3.5 focus:outline-none",
999
+ className: "focus:none placeholder-gray w-full rounded-lg border-none px-4 py-3.5 focus:outline-none",
1000
1000
  size,
1001
1001
  type
1002
1002
  }, rest)), rightAddon]
@@ -1314,7 +1314,8 @@ const RadioContext = createContext({
1314
1314
  name: void 0,
1315
1315
  onChange: noop,
1316
1316
  required: false,
1317
- value: void 0
1317
+ value: void 0,
1318
+ error: false
1318
1319
  });
1319
1320
  const Radio = forwardRef((props, ref) => {
1320
1321
  const _a = props, {
@@ -1330,12 +1331,13 @@ const Radio = forwardRef((props, ref) => {
1330
1331
  name,
1331
1332
  onChange,
1332
1333
  required,
1333
- value
1334
+ value,
1335
+ error
1334
1336
  } = useContext(RadioContext);
1335
1337
  return /* @__PURE__ */ jsxs("label", {
1336
- className: cx(className, "cursor-pointer"),
1338
+ className: cx(className, "flex cursor-pointer gap-2.5"),
1337
1339
  children: [/* @__PURE__ */ jsx("input", __spreadValues({
1338
- className: "radio",
1340
+ className: cx("radio", error && "border-red"),
1339
1341
  defaultChecked: !isControlled ? rest.value === defaultValue : void 0,
1340
1342
  checked: isControlled ? rest.value === value : void 0,
1341
1343
  name,
@@ -1352,6 +1354,8 @@ const RadioGroup = forwardRef((props, ref) => {
1352
1354
  className,
1353
1355
  defaultValue,
1354
1356
  description,
1357
+ error,
1358
+ id: idProp,
1355
1359
  children,
1356
1360
  label,
1357
1361
  name,
@@ -1362,6 +1366,8 @@ const RadioGroup = forwardRef((props, ref) => {
1362
1366
  "className",
1363
1367
  "defaultValue",
1364
1368
  "description",
1369
+ "error",
1370
+ "id",
1365
1371
  "children",
1366
1372
  "label",
1367
1373
  "name",
@@ -1379,15 +1385,22 @@ const RadioGroup = forwardRef((props, ref) => {
1379
1385
  name,
1380
1386
  onChange,
1381
1387
  required,
1382
- value
1383
- }), [defaultValue, isControlled, name, onChange, required, value]);
1384
- const groupId = useId();
1388
+ value,
1389
+ error: Boolean(error)
1390
+ }), [defaultValue, isControlled, name, onChange, required, value, error]);
1391
+ const groupId = useFallbackId(idProp);
1385
1392
  const labelId = `${groupId}:label`;
1386
- const helpId = `${groupId}:help`;
1393
+ const helpTextId = `${groupId}:help`;
1394
+ const errorMsgId = groupId + "err";
1395
+ const errorMsg = error;
1387
1396
  return /* @__PURE__ */ jsx(RadioContext.Provider, {
1388
1397
  value: group,
1389
1398
  children: /* @__PURE__ */ jsxs("div", __spreadProps(__spreadValues({
1390
- "aria-describedby": description ? helpId : void 0,
1399
+ "aria-describedby": cx({
1400
+ [errorMsgId]: errorMsg,
1401
+ [helpTextId]: description
1402
+ }) || void 0,
1403
+ "aria-invalid": !!error,
1391
1404
  "aria-labelledby": label ? labelId : void 0,
1392
1405
  className: cx(className, "flex flex-col gap-4"),
1393
1406
  role: "radiogroup",
@@ -1396,30 +1409,89 @@ const RadioGroup = forwardRef((props, ref) => {
1396
1409
  children: [label && /* @__PURE__ */ jsx(FormLabel, {
1397
1410
  id: labelId,
1398
1411
  isRequired: required,
1412
+ isInvalid: !!error,
1399
1413
  children: label
1400
- }), children, /* @__PURE__ */ jsx(FormHelperText, {
1401
- id: helpId,
1414
+ }), description && /* @__PURE__ */ jsx(FormHelperText, {
1415
+ id: helpTextId,
1402
1416
  children: description
1417
+ }), children, errorMsg && /* @__PURE__ */ jsx(FormErrorMessage, {
1418
+ id: errorMsgId,
1419
+ children: errorMsg
1403
1420
  })]
1404
1421
  }))
1405
1422
  });
1406
1423
  });
1407
- const Select = forwardRef((props, ref) => {
1424
+ const SelectPlain = forwardRef((props, ref) => {
1408
1425
  const _a = props, {
1409
1426
  children,
1410
- className
1427
+ className,
1428
+ isInvalid,
1429
+ size
1411
1430
  } = _a, rest = __objRest(_a, [
1412
1431
  "children",
1413
- "className"
1432
+ "className",
1433
+ "isInvalid",
1434
+ "size"
1414
1435
  ]);
1436
+ const isSmall = size === "small";
1415
1437
  return /* @__PURE__ */ jsxs("div", {
1416
- className: cx("relative", className),
1417
- children: [/* @__PURE__ */ jsx("select", __spreadProps(__spreadValues({}, rest), {
1418
- className: "focus:border-blue border-gray-dark w-full appearance-none rounded-lg border-2 border-solid bg-white px-4 py-3 focus:outline-none",
1438
+ className: cx(className, "relative", isSmall && "text-sm"),
1439
+ children: [/* @__PURE__ */ jsx("select", __spreadProps(__spreadValues({
1440
+ "aria-invalid": isInvalid
1441
+ }, rest), {
1442
+ className: cx("w-full cursor-pointer appearance-none border border-b-[3px] bg-white focus:-mt-0.5 focus:-ml-0.5 focus:border-[3px] focus:shadow focus:outline-none", isSmall ? "rounded px-3.5 py-2" : "rounded-lg px-4 py-3.5", isInvalid ? "border-red focus:border-red" : "focus:border-blue-dark border-black"),
1419
1443
  ref,
1420
1444
  children
1421
1445
  })), /* @__PURE__ */ jsx(ChevronDown, {
1422
- className: "absolute top-4 right-4"
1446
+ className: cx("pointer-events-none absolute top-0 bottom-0 my-auto", isSmall ? "right-3.5" : "right-4")
1447
+ })]
1448
+ });
1449
+ });
1450
+ const Select = forwardRef((props, ref) => {
1451
+ const _a = props, {
1452
+ description,
1453
+ error,
1454
+ id: idProp,
1455
+ label,
1456
+ disableValidation = false
1457
+ } = _a, rest = __objRest(_a, [
1458
+ "description",
1459
+ "error",
1460
+ "id",
1461
+ "label",
1462
+ "disableValidation"
1463
+ ]);
1464
+ const ownRef = useRef(null);
1465
+ const {
1466
+ validity,
1467
+ validationMessage
1468
+ } = useFormControlValidity(ownRef, !disableValidation);
1469
+ const id = useFallbackId(idProp);
1470
+ const helpTextId = id + "help";
1471
+ const errorMsgId = id + "err";
1472
+ const errorMsg = error || validationMessage;
1473
+ return /* @__PURE__ */ jsxs("div", {
1474
+ className: "grid gap-2",
1475
+ children: [/* @__PURE__ */ jsx(FormLabel, {
1476
+ htmlFor: id,
1477
+ isRequired: props.required,
1478
+ isInvalid: !!error || validity === "invalid",
1479
+ children: label
1480
+ }), description && /* @__PURE__ */ jsx(FormHelperText, {
1481
+ id: helpTextId,
1482
+ children: description
1483
+ }), /* @__PURE__ */ jsx(SelectPlain, __spreadProps(__spreadValues({
1484
+ id,
1485
+ ref: composeRefs(ownRef, ref)
1486
+ }, rest), {
1487
+ isInvalid: !!error || validity === "invalid",
1488
+ "aria-describedby": cx({
1489
+ [errorMsgId]: errorMsg,
1490
+ [helpTextId]: description
1491
+ }) || void 0
1492
+ })), errorMsg && /* @__PURE__ */ jsx(FormErrorMessage, {
1493
+ id: errorMsgId,
1494
+ children: errorMsg
1423
1495
  })]
1424
1496
  });
1425
1497
  });
@@ -1521,7 +1593,7 @@ const StepListBullet = (_a) => {
1521
1593
  ]);
1522
1594
  return /* @__PURE__ */ jsx("span", __spreadValues({
1523
1595
  "aria-hidden": true,
1524
- className: cx("text-green after:bg-gray-light before:bg-gray-light grid h-10 w-10 flex-none place-content-center justify-items-center rounded-full border-2 text-sm font-bold after:absolute after:bottom-0 after:w-0.5 after:translate-x-1/2 group-last:after:hidden md:h-20 md:w-20 md:text-xl ", {
1596
+ className: cx("text-green after:bg-gray-light before:bg-gray-light grid h-10 w-10 flex-none place-content-center justify-items-center rounded-full border-2 text-sm font-bold after:absolute after:bottom-0 after:w-0.5 after:translate-x-1/2 group-last:after:hidden md:h-20 md:w-20 md:text-xl", {
1525
1597
  "before:absolute before:top-0 before:bottom-1/2 before:w-0.5 before:-translate-y-5 before:translate-x-1/2 after:top-1/2 after:translate-y-5 group-first:before:hidden before:md:-translate-y-10 after:md:translate-y-10": align === "center",
1526
1598
  "after:top-10 after:-bottom-8 after:md:-bottom-12 after:md:top-20": align === "top"
1527
1599
  })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@obosbbl/grunnmuren-react",
3
- "version": "1.7.0",
3
+ "version": "1.9.0",
4
4
  "description": "OBOS Grunnmuren design system React components",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -17,26 +17,26 @@
17
17
  ],
18
18
  "types": "./dist/index.d.ts",
19
19
  "devDependencies": {
20
- "@babel/core": "7.20.2",
21
- "@storybook/addon-controls": "6.5.14",
22
- "@storybook/addon-docs": "6.5.14",
20
+ "@babel/core": "7.20.7",
21
+ "@storybook/addon-controls": "6.5.15",
22
+ "@storybook/addon-docs": "6.5.15",
23
23
  "@storybook/addon-postcss": "2.0.0",
24
- "@storybook/builder-webpack5": "6.5.14",
25
- "@storybook/manager-webpack5": "6.5.14",
26
- "@storybook/react": "6.5.14",
27
- "@types/react": "18.0.25",
28
- "@types/react-dom": "18.0.9",
24
+ "@storybook/builder-webpack5": "6.5.15",
25
+ "@storybook/manager-webpack5": "6.5.15",
26
+ "@storybook/react": "6.5.15",
27
+ "@types/react": "18.0.26",
28
+ "@types/react-dom": "18.0.10",
29
29
  "@vitejs/plugin-react": "1.3.2",
30
- "postcss": "8.4.19",
30
+ "postcss": "8.4.20",
31
31
  "react": "18.2.0",
32
32
  "react-dom": "18.2.0",
33
33
  "require-from-string": "2.0.2",
34
34
  "rimraf": "3.0.2",
35
35
  "tailwindcss": "3.2.4",
36
- "type-fest": "3.3.0",
36
+ "type-fest": "3.5.0",
37
37
  "vite": "2.9.15",
38
38
  "webpack": "5.75.0",
39
- "@obosbbl/grunnmuren-tailwind": "0.8.3"
39
+ "@obosbbl/grunnmuren-tailwind": "0.8.4"
40
40
  },
41
41
  "dependencies": {
42
42
  "@seznam/compose-react-refs": "1.0.6",
@@ -46,7 +46,7 @@
46
46
  "@obosbbl/grunnmuren-icons": "^0.5.1"
47
47
  },
48
48
  "peerDependencies": {
49
- "@obosbbl/grunnmuren-tailwind": "^0.8.3",
49
+ "@obosbbl/grunnmuren-tailwind": "^0.8.4",
50
50
  "react": "^18"
51
51
  },
52
52
  "peerDependenciesMeta": {