@prokodo/ui 0.0.41 → 0.0.43

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 (100) hide show
  1. package/README.md +5 -2
  2. package/dist/components/accordion/Accordion.client.js +1 -1
  3. package/dist/components/animatedText/AnimatedText.client.js +4 -4
  4. package/dist/components/dialog/Dialog.client.js +9 -3
  5. package/dist/components/dialog/Dialog.module.scss.js +2 -0
  6. package/dist/components/dialog/Dialog.view.js +72 -57
  7. package/dist/components/dynamic-list/DynamicList.client.js +91 -0
  8. package/dist/components/dynamic-list/DynamicList.js +12 -0
  9. package/dist/components/dynamic-list/DynamicList.lazy.js +12 -0
  10. package/dist/components/dynamic-list/DynamicList.module.scss.js +20 -0
  11. package/dist/components/dynamic-list/DynamicList.server.js +15 -0
  12. package/dist/components/dynamic-list/DynamicList.view.js +128 -0
  13. package/dist/components/dynamic-list/index.js +4 -0
  14. package/dist/components/form/Form.client.js +4 -0
  15. package/dist/components/form/Form.server.js +2 -0
  16. package/dist/components/form/Form.view.js +2 -3
  17. package/dist/components/form/FormField.client.js +22 -1
  18. package/dist/components/form/FormField.server.js +3 -1
  19. package/dist/components/form/FormResponse.js +1 -0
  20. package/dist/components/label/Label.js +48 -38
  21. package/dist/components/list/List.js +11 -10
  22. package/dist/components/list/List.module.scss.js +1 -0
  23. package/dist/components/progressBar/ProgressBar.client.js +34 -0
  24. package/dist/components/progressBar/ProgressBar.js +13 -0
  25. package/dist/components/progressBar/ProgressBar.lazy.js +15 -0
  26. package/dist/components/progressBar/ProgressBar.module.scss.js +35 -0
  27. package/dist/components/progressBar/ProgressBar.server.js +11 -0
  28. package/dist/components/progressBar/ProgressBar.view.js +55 -0
  29. package/dist/components/progressBar/index.js +4 -0
  30. package/dist/components/select/Select.view.js +10 -1
  31. package/dist/components/sidenav/SideNav.client.js +22 -2
  32. package/dist/components/sidenav/SideNav.module.scss.js +1 -0
  33. package/dist/components/sidenav/SideNav.view.js +2 -2
  34. package/dist/components/snackbar/Snackbar.client.js +38 -0
  35. package/dist/components/snackbar/Snackbar.js +12 -0
  36. package/dist/components/snackbar/Snackbar.lazy.js +12 -0
  37. package/dist/components/snackbar/Snackbar.module.scss.js +30 -0
  38. package/dist/components/snackbar/Snackbar.server.js +12 -0
  39. package/dist/components/snackbar/Snackbar.view.js +55 -0
  40. package/dist/components/snackbar/SnackbarProvider.client.js +79 -0
  41. package/dist/components/snackbar/SnackbarProvider.context.js +11 -0
  42. package/dist/components/snackbar/SnackbarProvider.js +14 -0
  43. package/dist/components/snackbar/SnackbarProvider.lazy.js +15 -0
  44. package/dist/components/snackbar/index.js +10 -0
  45. package/dist/components/stepper/Stepper.view.js +5 -2
  46. package/dist/components/table/Table.js +9 -8
  47. package/dist/components/table/TableCell.js +4 -3
  48. package/dist/constants/project.js +1 -1
  49. package/dist/helpers/createIsland.js +8 -5
  50. package/dist/helpers/createLazyWrapper.js +13 -8
  51. package/dist/index.js +6 -0
  52. package/dist/tsconfig.build.tsbuildinfo +1 -1
  53. package/dist/types/components/accordion/Accordion.d.ts +1 -1
  54. package/dist/types/components/accordion/Accordion.lazy.d.ts +1 -1
  55. package/dist/types/components/accordion/Accordion.model.d.ts +1 -1
  56. package/dist/types/components/dialog/Dialog.d.ts +1 -1
  57. package/dist/types/components/dialog/Dialog.lazy.d.ts +1 -1
  58. package/dist/types/components/dialog/Dialog.model.d.ts +7 -3
  59. package/dist/types/components/dialog/Dialog.view.d.ts +1 -1
  60. package/dist/types/components/dynamic-list/DynamicList.client.d.ts +4 -0
  61. package/dist/types/components/dynamic-list/DynamicList.d.ts +4 -0
  62. package/dist/types/components/dynamic-list/DynamicList.lazy.d.ts +5 -0
  63. package/dist/types/components/dynamic-list/DynamicList.model.d.ts +32 -0
  64. package/dist/types/components/dynamic-list/DynamicList.server.d.ts +3 -0
  65. package/dist/types/components/dynamic-list/DynamicList.view.d.ts +12 -0
  66. package/dist/types/components/dynamic-list/index.d.ts +2 -0
  67. package/dist/types/components/form/Form.d.ts +1 -1
  68. package/dist/types/components/form/Form.lazy.d.ts +1 -1
  69. package/dist/types/components/form/Form.model.d.ts +9 -5
  70. package/dist/types/components/form/index.d.ts +1 -2
  71. package/dist/types/components/label/Label.model.d.ts +9 -2
  72. package/dist/types/components/link/Link.model.d.ts +2 -2
  73. package/dist/types/components/list/List.model.d.ts +11 -5
  74. package/dist/types/components/progressBar/ProgressBar.client.d.ts +3 -0
  75. package/dist/types/components/progressBar/ProgressBar.d.ts +12 -0
  76. package/dist/types/components/progressBar/ProgressBar.lazy.d.ts +13 -0
  77. package/dist/types/components/progressBar/ProgressBar.model.d.ts +14 -0
  78. package/dist/types/components/progressBar/ProgressBar.server.d.ts +3 -0
  79. package/dist/types/components/progressBar/ProgressBar.view.d.ts +3 -0
  80. package/dist/types/components/progressBar/index.d.ts +2 -0
  81. package/dist/types/components/select/Select.model.d.ts +3 -2
  82. package/dist/types/components/sidenav/SideNav.client.d.ts +1 -1
  83. package/dist/types/components/sidenav/SideNav.model.d.ts +2 -0
  84. package/dist/types/components/snackbar/Snackbar.client.d.ts +5 -0
  85. package/dist/types/components/snackbar/Snackbar.d.ts +4 -0
  86. package/dist/types/components/snackbar/Snackbar.lazy.d.ts +5 -0
  87. package/dist/types/components/snackbar/Snackbar.model.d.ts +20 -0
  88. package/dist/types/components/snackbar/Snackbar.server.d.ts +3 -0
  89. package/dist/types/components/snackbar/Snackbar.view.d.ts +7 -0
  90. package/dist/types/components/snackbar/SnackbarProvider.client.d.ts +4 -0
  91. package/dist/types/components/snackbar/SnackbarProvider.context.d.ts +6 -0
  92. package/dist/types/components/snackbar/SnackbarProvider.d.ts +3 -0
  93. package/dist/types/components/snackbar/SnackbarProvider.lazy.d.ts +5 -0
  94. package/dist/types/components/snackbar/SnackbarProvider.model.d.ts +25 -0
  95. package/dist/types/components/snackbar/index.d.ts +6 -0
  96. package/dist/types/components/stepper/Stepper.model.d.ts +1 -1
  97. package/dist/types/components/table/Table.model.d.ts +3 -2
  98. package/dist/types/index.d.ts +3 -0
  99. package/dist/ui.css +745 -16
  100. package/package.json +14 -2
package/README.md CHANGED
@@ -21,7 +21,7 @@
21
21
  - ✨ **Adaptive Island Components (AIC)**: A rendering strategy where each component loads only the JavaScript it needs — when needed.
22
22
  - ⚡️ **Modern stack**: Vite, React 19, TypeScript, and SCSS Modules
23
23
  - 💅 **Design consistency**: Theming via design tokens and BEM-style naming
24
- - 🧩 **Component-rich**: 35+ reusable UI components
24
+ - 🧩 **Component-rich**: 40+ reusable UI components
25
25
  - 🧪 **Reliable**: Fully tested with Jest and Testing Library
26
26
  - 📚 **Storybook**: Explore the components at [ui.prokodo.com](https://ui.prokodo.com)
27
27
  - 📦 **Ready-to-install**: Distributed via npm for non-production use under the BUSL-1.1 license
@@ -131,7 +131,7 @@ export default function GalleryPage() {
131
131
  ### Compatibility of the components
132
132
 
133
133
  - ✅ = Available as AIC (renders zero-JS RSC and self-hydrates when needed) and can also used as a client‐only entry.
134
- - \- = RSC (AIC) only; no client‐side bundle. (Useable in both, but best practice to use in RSC only)
134
+ - \- = RSC (AIC) only; no client‐side bundle needed. (Useable in both, but best practice to use in RSC only)
135
135
 
136
136
  | Component | ✅ AIC (RSC + optional client) | ✅ SSR-Compatible (`"use client"`) |
137
137
  |-----------------------|:--------------------------------:|:---------------------------------:|
@@ -148,6 +148,7 @@ export default function GalleryPage() {
148
148
  | DatePicker | ✅ | ✅ |
149
149
  | Dialog | ✅ | ✅ |
150
150
  | Drawer | ✅ | ✅ |
151
+ | DynamicList | ✅ | ✅ |
151
152
  | Form | ✅ | ✅ |
152
153
  | FormResponse | ✅ | – |
153
154
  | Grid/GridRow | ✅ | – |
@@ -166,12 +167,14 @@ export default function GalleryPage() {
166
167
  | PostTeaser | ❌ (Experimental - Coming soon) | – |
167
168
  | PostWidget | ❌ (Experimental - Coming soon) | – |
168
169
  | PostWidgetCarousel | ❌ (Experimental - Coming soon) | - |
170
+ | ProgressBar | ✅ | ✅ |
169
171
  | Quote | ✅ | – |
170
172
  | RichText | ✅ | ✅ |
171
173
  | Select | ✅ | ✅ |
172
174
  | SideNav | ✅ | ✅ |
173
175
  | Skeleton | ✅ | – |
174
176
  | Slider | ✅ | ✅ |
177
+ | Snackbar & Provider | ✅ | ✅ |
175
178
  | Stepper | ✅ | ✅ |
176
179
  | Switch | ✅ | ✅ |
177
180
  | Table | ✅ | – |
@@ -11,7 +11,7 @@ function AccordionClient(props) {
11
11
  (index, e) => {
12
12
  const next = expandedIndex === index ? null : index;
13
13
  setExpandedIndex(next);
14
- onChange == null ? void 0 : onChange(index, e, next !== null);
14
+ onChange == null ? void 0 : onChange(next !== null ? index : void 0, e, next !== null);
15
15
  },
16
16
  [expandedIndex, onChange]
17
17
  );
@@ -17,21 +17,21 @@ function AnimatedTextClient({
17
17
  const t0 = window.setTimeout(() => {
18
18
  const id = window.setInterval(() => {
19
19
  setIndex((i) => {
20
- if (i + 1 >= children.length) {
20
+ if (i + 1 >= (children == null ? void 0 : children.length)) {
21
21
  clearInterval(id);
22
- return children.length;
22
+ return children == null ? void 0 : children.length;
23
23
  }
24
24
  return i + 1;
25
25
  });
26
26
  }, speed);
27
27
  }, delay);
28
28
  return () => clearTimeout(t0);
29
- }, [children.length, delay, disabled, speed]);
29
+ }, [children == null ? void 0 : children.length, delay, disabled, speed]);
30
30
  return /* @__PURE__ */ jsx(
31
31
  AnimatedTextView,
32
32
  {
33
33
  ...rest,
34
- text: children.slice(0, index)
34
+ text: children == null ? void 0 : children.slice(0, index)
35
35
  }
36
36
  );
37
37
  }
@@ -5,7 +5,7 @@ import { jsx } from "react/jsx-runtime";
5
5
  import { forwardRef, useRef, useState, useCallback, useEffect, useImperativeHandle } from "react";
6
6
  import { DialogView } from "./Dialog.view.js";
7
7
  const FADE_DURATION = 300;
8
- function DialogClient({ open = false, closeOnBackdropClick = true, onChange, ...props }, ref) {
8
+ function DialogClient({ open = false, closeOnBackdropClick = true, onChange, onClose, ...props }, ref) {
9
9
  const triggerRef = useRef(null);
10
10
  const closeButtonRef = useRef(null);
11
11
  const containerRef = useRef(null);
@@ -22,12 +22,13 @@ function DialogClient({ open = false, closeOnBackdropClick = true, onChange, ...
22
22
  }, [isOpen]);
23
23
  const closeDialog = useCallback((reson) => {
24
24
  setIsOpen(false);
25
+ onClose == null ? void 0 : onClose();
25
26
  setTimeout(() => {
26
27
  var _a;
27
28
  onChange == null ? void 0 : onChange({}, reson ?? "backdropClick", false);
28
29
  (_a = triggerRef.current) == null ? void 0 : _a.focus();
29
30
  }, FADE_DURATION);
30
- }, [onChange]);
31
+ }, [onChange, onClose]);
31
32
  useImperativeHandle(
32
33
  ref,
33
34
  () => ({ openDialog, closeDialog }),
@@ -80,7 +81,12 @@ function DialogClient({ open = false, closeOnBackdropClick = true, onChange, ...
80
81
  }, "onMouseDown")
81
82
  },
82
83
  onClose: closeDialog,
83
- onMouseDown: /* @__PURE__ */ __name((e) => e.stopPropagation(), "onMouseDown")
84
+ onMouseDown: /* @__PURE__ */ __name((e) => e.stopPropagation(), "onMouseDown"),
85
+ onCloseKeyDown: /* @__PURE__ */ __name((e) => {
86
+ if (e.key === "Enter") {
87
+ closeDialog();
88
+ }
89
+ }, "onCloseKeyDown")
84
90
  }
85
91
  );
86
92
  }
@@ -7,6 +7,8 @@ const styles = {
7
7
  "prokodo-Dialog__container--scroll-paper": "prokodo-Dialog__container--scroll-paper",
8
8
  "prokodo-Dialog__container--scroll-body": "prokodo-Dialog__container--scroll-body",
9
9
  "prokodo-Dialog__header": "prokodo-Dialog__header",
10
+ "prokodo-Dialog__header__button": "prokodo-Dialog__header__button",
11
+ "prokodo-Dialog__header__button__icon": "prokodo-Dialog__header__button__icon",
10
12
  "prokodo-Dialog__close": "prokodo-Dialog__close",
11
13
  "prokodo-Dialog__close__label": "prokodo-Dialog__close__label",
12
14
  "prokodo-Dialog__title--is-hidden": "prokodo-Dialog__title--is-hidden",
@@ -5,6 +5,7 @@ import { create } from "../../helpers/bem.js";
5
5
  import styles from "./Dialog.module.scss.js";
6
6
  import { Button } from "../button/Button.js";
7
7
  import { Headline } from "../headline/Headline.js";
8
+ import { Icon } from "../icon/Icon.js";
8
9
  const bem = create(styles, "Dialog");
9
10
  function DialogView({
10
11
  open,
@@ -25,6 +26,7 @@ function DialogView({
25
26
  titleProps = {},
26
27
  children,
27
28
  onClose,
29
+ onCloseKeyDown,
28
30
  wrapperProps,
29
31
  closeOnBackdropClick = true,
30
32
  closeButtonProps,
@@ -39,69 +41,82 @@ function DialogView({
39
41
  fullScreen,
40
42
  "is-visible": Boolean(open)
41
43
  };
42
- const renderDialog = /* @__PURE__ */ __name(() => /* @__PURE__ */ jsxs(
43
- "div",
44
- {
45
- "aria-describedby": "dialog-content",
46
- "aria-labelledby": "dialog-title",
47
- "aria-modal": "true",
48
- role: "dialog",
49
- ...rest,
50
- className: bem(void 0, wrapperMods, className),
51
- children: [
52
- /* @__PURE__ */ jsxs("div", { ref: containerRef, className: bem("container", containerMods), children: [
53
- /* @__PURE__ */ jsxs("div", { className: bem("header", void 0, classNameHeader), children: [
54
- /* @__PURE__ */ jsxs("div", { children: [
55
- /* @__PURE__ */ jsx(
56
- Headline,
44
+ const renderDialog = /* @__PURE__ */ __name(() => {
45
+ var _a;
46
+ return /* @__PURE__ */ jsxs(
47
+ "div",
48
+ {
49
+ "aria-describedby": "dialog-content",
50
+ "aria-labelledby": "dialog-title",
51
+ "aria-modal": "true",
52
+ role: "dialog",
53
+ ...rest,
54
+ className: bem(void 0, wrapperMods, className),
55
+ children: [
56
+ /* @__PURE__ */ jsxs("div", { ref: containerRef, className: bem("container", containerMods), children: [
57
+ /* @__PURE__ */ jsxs("div", { className: bem("header", void 0, classNameHeader), children: [
58
+ /* @__PURE__ */ jsxs("div", { children: [
59
+ /* @__PURE__ */ jsx(
60
+ Headline,
61
+ {
62
+ ...titleProps,
63
+ className: bem("title", { "is-hidden": hideTitle }),
64
+ id: "dialog-title",
65
+ children: title
66
+ }
67
+ ),
68
+ renderHeader == null ? void 0 : renderHeader()
69
+ ] }),
70
+ !Boolean(hideCloseButton) && /* @__PURE__ */ jsxs(
71
+ "button",
57
72
  {
58
- ...titleProps,
59
- className: bem("title", { "is-hidden": hideTitle }),
60
- id: "dialog-title",
61
- children: title
73
+ ...closeButtonProps,
74
+ ref: closeButtonRef,
75
+ "aria-label": (closeButtonProps == null ? void 0 : closeButtonProps["aria-label"]) ?? (translations == null ? void 0 : translations.close),
76
+ className: bem("header__button", void 0, closeButtonProps == null ? void 0 : closeButtonProps.className),
77
+ onClick: onClose,
78
+ onKeyDown: onCloseKeyDown,
79
+ children: [
80
+ /* @__PURE__ */ jsx(
81
+ Icon,
82
+ {
83
+ name: "Cancel01Icon",
84
+ size: "xs",
85
+ ...closeButtonProps == null ? void 0 : closeButtonProps.iconProps,
86
+ className: bem("header__button__icon", void 0, (_a = closeButtonProps == null ? void 0 : closeButtonProps.iconProps) == null ? void 0 : _a.className)
87
+ }
88
+ ),
89
+ (closeButtonProps == null ? void 0 : closeButtonProps.title) ?? (translations == null ? void 0 : translations.close) ?? "Close"
90
+ ]
62
91
  }
63
- ),
64
- renderHeader == null ? void 0 : renderHeader()
92
+ )
65
93
  ] }),
66
- !Boolean(hideCloseButton) && /* @__PURE__ */ jsx(
67
- Button,
94
+ /* @__PURE__ */ jsx("div", { "aria-hidden": "true", tabIndex: 0 }),
95
+ /* @__PURE__ */ jsx(
96
+ "div",
68
97
  {
69
- "aria-label": translations == null ? void 0 : translations.close,
70
- color: "inherit",
71
- iconProps: { name: "Cancel01Icon", size: "sm" },
72
- variant: "outlined",
73
- ...closeButtonProps,
74
- ref: closeButtonRef,
75
- title: (translations == null ? void 0 : translations.close) ?? "Close",
76
- onClick: onClose
98
+ ...contentProps,
99
+ ref: contentRef,
100
+ id: "dialog-content",
101
+ className: bem(
102
+ "content",
103
+ { [`scroll-${scroll}`]: true },
104
+ contentProps.className
105
+ ),
106
+ children
77
107
  }
78
- )
108
+ ),
109
+ actions.length > 0 && /* @__PURE__ */ jsxs("div", { className: bem("actions"), children: [
110
+ /* @__PURE__ */ jsx("div", { "aria-hidden": "true", tabIndex: 0 }),
111
+ actions.map((action) => /* @__PURE__ */ jsx(Button, { ...action, title: (action == null ? void 0 : action.title) ?? "" }, action.id)),
112
+ /* @__PURE__ */ jsx("div", { "aria-hidden": "true", tabIndex: 0 })
113
+ ] })
79
114
  ] }),
80
- /* @__PURE__ */ jsx("div", { "aria-hidden": "true", tabIndex: 0 }),
81
- /* @__PURE__ */ jsx(
82
- "div",
83
- {
84
- ...contentProps,
85
- ref: contentRef,
86
- id: "dialog-content",
87
- className: bem(
88
- "content",
89
- { [`scroll-${scroll}`]: true },
90
- contentProps.className
91
- ),
92
- children
93
- }
94
- ),
95
- actions.length > 0 && /* @__PURE__ */ jsxs("div", { className: bem("actions"), children: [
96
- /* @__PURE__ */ jsx("div", { "aria-hidden": "true", tabIndex: 0 }),
97
- actions.map((action) => /* @__PURE__ */ jsx(Button, { ...action, title: (action == null ? void 0 : action.title) ?? "" }, action.id)),
98
- /* @__PURE__ */ jsx("div", { "aria-hidden": "true", tabIndex: 0 })
99
- ] })
100
- ] }),
101
- containerChildren
102
- ]
103
- }
104
- ), "renderDialog");
115
+ containerChildren
116
+ ]
117
+ }
118
+ );
119
+ }, "renderDialog");
105
120
  if (!closeOnBackdropClick || fullScreen) return renderDialog();
106
121
  return /* @__PURE__ */ jsx(
107
122
  "div",
@@ -0,0 +1,91 @@
1
+ "use client";
2
+ var __defProp = Object.defineProperty;
3
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
4
+ import { jsx } from "react/jsx-runtime";
5
+ import { memo, useState, useEffect, useCallback } from "react";
6
+ import { isString } from "../../helpers/validations.js";
7
+ import { DynamicListView } from "./DynamicList.view.js";
8
+ function DynamicListClient({
9
+ fields,
10
+ value: controlledItems,
11
+ onChange,
12
+ buttonAddProps,
13
+ buttonDeleteProps,
14
+ ...props
15
+ }) {
16
+ const isSingle = fields.length === 1;
17
+ const [items, setItems] = useState(
18
+ () => controlledItems ?? []
19
+ );
20
+ useEffect(() => {
21
+ if (controlledItems !== void 0) {
22
+ setItems(controlledItems);
23
+ }
24
+ }, [controlledItems]);
25
+ const handleChange = useCallback(
26
+ (e) => {
27
+ const target = e.target;
28
+ const idx = Number(target.dataset.index);
29
+ const key = target.dataset.field;
30
+ const { value } = target;
31
+ if (Number.isNaN(idx) || !isString(key)) return;
32
+ const next = items.map((it, i) => {
33
+ if (i !== idx) return it;
34
+ return isSingle ? value : { ...it, [key]: value };
35
+ });
36
+ setItems(next);
37
+ onChange == null ? void 0 : onChange(next);
38
+ },
39
+ [items, onChange, isSingle]
40
+ );
41
+ const handleAdd = useCallback(
42
+ (e) => {
43
+ var _a;
44
+ const empty = isSingle ? "" : fields.reduce((obj, f) => {
45
+ obj[f.name] = "";
46
+ return obj;
47
+ }, {});
48
+ const next = [...items, empty];
49
+ setItems(next);
50
+ (_a = buttonAddProps == null ? void 0 : buttonAddProps.onClick) == null ? void 0 : _a.call(buttonAddProps, e);
51
+ onChange == null ? void 0 : onChange(next);
52
+ },
53
+ [items, onChange, isSingle, fields, buttonAddProps]
54
+ );
55
+ const handleDelete = useCallback(
56
+ (e) => {
57
+ var _a;
58
+ const idx = Number(e.currentTarget.dataset.index);
59
+ if (Number.isNaN(idx)) return;
60
+ const next = items.filter((_, i) => i !== idx);
61
+ setItems(next);
62
+ (_a = buttonDeleteProps == null ? void 0 : buttonDeleteProps.onClick) == null ? void 0 : _a.call(buttonDeleteProps, e, idx);
63
+ onChange == null ? void 0 : onChange(next);
64
+ },
65
+ [items, onChange, buttonDeleteProps]
66
+ );
67
+ return /* @__PURE__ */ jsx(
68
+ DynamicListView,
69
+ {
70
+ ...props,
71
+ fields,
72
+ value: items,
73
+ buttonAddProps: {
74
+ ...buttonAddProps,
75
+ onClick: handleAdd
76
+ },
77
+ buttonDeleteProps: {
78
+ ...buttonDeleteProps,
79
+ onClick: handleDelete
80
+ },
81
+ fieldProps: {
82
+ onChange: handleChange
83
+ }
84
+ }
85
+ );
86
+ }
87
+ __name(DynamicListClient, "DynamicListClient");
88
+ const DynamicListClient$1 = memo(DynamicListClient);
89
+ export {
90
+ DynamicListClient$1 as default
91
+ };
@@ -0,0 +1,12 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+ import { createIsland } from "../../helpers/createIsland.js";
4
+ import DynamicListServer from "./DynamicList.server.js";
5
+ const DynamicList = createIsland({
6
+ name: "DynamicList",
7
+ Server: DynamicListServer,
8
+ loadLazy: /* @__PURE__ */ __name(() => import("./DynamicList.lazy.js"), "loadLazy")
9
+ });
10
+ export {
11
+ DynamicList
12
+ };
@@ -0,0 +1,12 @@
1
+ "use client";
2
+ import { createLazyWrapper } from "../../helpers/createLazyWrapper.js";
3
+ import DynamicListClient from "./DynamicList.client.js";
4
+ import DynamicListServer from "./DynamicList.server.js";
5
+ const DynamicList_lazy = createLazyWrapper({
6
+ name: "DynamicList",
7
+ Client: DynamicListClient,
8
+ Server: DynamicListServer
9
+ });
10
+ export {
11
+ DynamicList_lazy as default
12
+ };
@@ -0,0 +1,20 @@
1
+ const gradientMove = "gradientMove";
2
+ const fadeInKeyframe = "fadeInKeyframe";
3
+ const styles = {
4
+ "prokodo-DynamicList": "prokodo-DynamicList",
5
+ "prokodo-DynamicList__list": "prokodo-DynamicList__list",
6
+ "prokodo-DynamicList__list__item": "prokodo-DynamicList__list__item",
7
+ "prokodo-DynamicList__list__item--is-multi": "prokodo-DynamicList__list__item--is-multi",
8
+ "prokodo-DynamicList__field--is-multi": "prokodo-DynamicList__field--is-multi",
9
+ "prokodo-DynamicList__delete__button--is-multi": "prokodo-DynamicList__delete__button--is-multi",
10
+ "prokodo-DynamicList__helperText": "prokodo-DynamicList__helperText",
11
+ "prokodo-DynamicList__helperText__content": "prokodo-DynamicList__helperText__content",
12
+ "prokodo-DynamicList__helperText__content--is-error": "prokodo-DynamicList__helperText__content--is-error",
13
+ gradientMove,
14
+ fadeInKeyframe
15
+ };
16
+ export {
17
+ styles as default,
18
+ fadeInKeyframe,
19
+ gradientMove
20
+ };
@@ -0,0 +1,15 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+ import { jsx } from "react/jsx-runtime";
4
+ import { DynamicListView } from "./DynamicList.view.js";
5
+ function DynamicListServer(props) {
6
+ const { buttonDeleteProps, ...rest } = props;
7
+ return /* @__PURE__ */ jsx(DynamicListView, { ...rest, buttonDeleteProps: {
8
+ ...buttonDeleteProps,
9
+ onClick: void 0
10
+ } });
11
+ }
12
+ __name(DynamicListServer, "DynamicListServer");
13
+ export {
14
+ DynamicListServer as default
15
+ };
@@ -0,0 +1,128 @@
1
+ var __defProp = Object.defineProperty;
2
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
3
+ import { jsxs, jsx } from "react/jsx-runtime";
4
+ import { create } from "../../helpers/bem.js";
5
+ import { isString } from "../../helpers/validations.js";
6
+ import styles from "./DynamicList.module.scss.js";
7
+ import { Input } from "../input/Input.js";
8
+ import { Button } from "../button/Button.js";
9
+ import { Label } from "../label/Label.js";
10
+ const bem = create(styles, "DynamicList");
11
+ function DynamicListView({
12
+ id,
13
+ label,
14
+ labelProps,
15
+ disabled,
16
+ required,
17
+ className,
18
+ classNameList,
19
+ fields,
20
+ value = [],
21
+ fieldProps,
22
+ buttonAddProps,
23
+ buttonDeleteProps,
24
+ name = "items",
25
+ errorText,
26
+ helperText
27
+ }) {
28
+ const isError = Boolean(errorText);
29
+ const hasHelper = Boolean(helperText);
30
+ const errorId = isError ? `${id}-error` : void 0;
31
+ const helperId = hasHelper ? `${id}-helper` : void 0;
32
+ const single = fields.length === 1;
33
+ const mod = { "is-multi": !Boolean(single) };
34
+ return /* @__PURE__ */ jsxs(
35
+ "fieldset",
36
+ {
37
+ "aria-describedby": isError ? errorId : helperId,
38
+ "aria-labelledby": `${name}-legend`,
39
+ className: bem(void 0, void 0, className),
40
+ children: [
41
+ isString(label) && /* @__PURE__ */ jsx(
42
+ Label,
43
+ {
44
+ ...labelProps,
45
+ "aria-disabled": disabled,
46
+ className: bem("list-label", void 0, labelProps == null ? void 0 : labelProps.className),
47
+ error: isError,
48
+ id: (labelProps == null ? void 0 : labelProps.id) ?? `${name}-legend`,
49
+ label,
50
+ required,
51
+ type: "legend"
52
+ }
53
+ ),
54
+ value.map((item, idx) => /* @__PURE__ */ jsxs(
55
+ "ul",
56
+ {
57
+ "aria-describedby": errorId ?? helperId,
58
+ className: bem("list", mod, classNameList),
59
+ children: [
60
+ /* @__PURE__ */ jsx("li", { className: bem("list__item"), children: fields.map((field) => /* @__PURE__ */ jsx(
61
+ Input,
62
+ {
63
+ fullWidth: true,
64
+ ...field,
65
+ ...fieldProps,
66
+ className: bem("field", mod, field == null ? void 0 : field.className),
67
+ "data-field": field == null ? void 0 : field.name,
68
+ "data-index": idx,
69
+ disabled: disabled ?? (fieldProps == null ? void 0 : fieldProps.disabled) ?? (field == null ? void 0 : field.disabled),
70
+ id: `${name}-${idx}-${field.name}`,
71
+ required: required ?? (fieldProps == null ? void 0 : fieldProps.required) ?? (field == null ? void 0 : field.required),
72
+ value: single ? item : item[field.name],
73
+ name: single ? `${name}[${idx}]` : `${name}[${idx}].${field.name}`
74
+ },
75
+ field.name
76
+ )) }),
77
+ /* @__PURE__ */ jsx(
78
+ Button,
79
+ {
80
+ "aria-label": `Remove ${label} entry ${idx + 1}`,
81
+ color: "error",
82
+ "data-index": idx,
83
+ iconProps: {
84
+ name: "Delete02Icon"
85
+ },
86
+ ...buttonDeleteProps,
87
+ className: bem("delete__button", mod, buttonDeleteProps == null ? void 0 : buttonDeleteProps.className)
88
+ }
89
+ )
90
+ ]
91
+ },
92
+ idx
93
+ )),
94
+ /* @__PURE__ */ jsx(
95
+ Button,
96
+ {
97
+ title: "Add item",
98
+ variant: "outlined",
99
+ ...buttonAddProps,
100
+ className: bem("button", void 0, buttonAddProps == null ? void 0 : buttonAddProps.className)
101
+ }
102
+ ),
103
+ (isError || hasHelper) && /* @__PURE__ */ jsx(
104
+ "div",
105
+ {
106
+ "aria-live": isError ? "assertive" : "polite",
107
+ className: bem("helperText"),
108
+ id: errorId ?? helperId,
109
+ role: isError ? "alert" : void 0,
110
+ children: /* @__PURE__ */ jsx(
111
+ "span",
112
+ {
113
+ className: bem("helperText__content", {
114
+ "is-error": isError
115
+ }),
116
+ children: errorText ?? helperText
117
+ }
118
+ )
119
+ }
120
+ )
121
+ ]
122
+ }
123
+ );
124
+ }
125
+ __name(DynamicListView, "DynamicListView");
126
+ export {
127
+ DynamicListView
128
+ };
@@ -0,0 +1,4 @@
1
+ import { DynamicList } from "./DynamicList.js";
2
+ export {
3
+ DynamicList
4
+ };
@@ -66,6 +66,10 @@ const FormClient = memo((props) => {
66
66
  (field, value) => {
67
67
  const idx = formState.findIndex((f) => f.name === field.name);
68
68
  if (idx < 0) return;
69
+ if (field.fieldType === "dynamic-list") {
70
+ updateSingleField(idx, { value });
71
+ return;
72
+ }
69
73
  if (!field.conditions || field.conditions.length === 0) {
70
74
  updateSingleField(idx, { value });
71
75
  return;
@@ -6,6 +6,8 @@ const FormServer = /* @__PURE__ */ __name((props) => {
6
6
  const {
7
7
  fields,
8
8
  messages,
9
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
10
+ onChangeForm,
9
11
  ...rest
10
12
  } = props;
11
13
  const emptyState = fields ?? [];
@@ -3,7 +3,7 @@ var __name = (target, value) => __defProp(target, "name", { value, configurable:
3
3
  import { jsxs, jsx } from "react/jsx-runtime";
4
4
  import { createElement } from "react";
5
5
  import { create } from "../../helpers/bem.js";
6
- import { isArray } from "../../helpers/validations.js";
6
+ import { isArray, isNull } from "../../helpers/validations.js";
7
7
  import styles from "./Form.module.scss.js";
8
8
  import { FormField } from "./FormField.js";
9
9
  import { FormResponse } from "./FormResponse.js";
@@ -83,10 +83,9 @@ const FormView = /* @__PURE__ */ __name(({
83
83
  ] }),
84
84
  /* @__PURE__ */ jsxs("div", { className: bem("footer"), children: [
85
85
  (hideResponse === false || hideResponse === void 0) && /* @__PURE__ */ jsx(FormResponse, { messages: formMessages }),
86
- ((_a = honeypot == null ? void 0 : honeypot.value) == null ? void 0 : _a.length) === 0 && /* @__PURE__ */ jsx(
86
+ !isNull(button) && ((_a = honeypot == null ? void 0 : honeypot.value) == null ? void 0 : _a.length) === 0 && /* @__PURE__ */ jsx(
87
87
  Button,
88
88
  {
89
- fullWidth: true,
90
89
  "aria-label": "Submit form",
91
90
  title: "Submit",
92
91
  type: "submit",
@@ -5,6 +5,7 @@ import { jsx } from "react/jsx-runtime";
5
5
  import { useCallback } from "react";
6
6
  import { create } from "../../helpers/bem.js";
7
7
  import styles from "./FormField.module.scss.js";
8
+ import { DynamicList } from "../dynamic-list/DynamicList.js";
8
9
  import { GridRow } from "../grid/GridRow.js";
9
10
  import { DatePicker } from "../datePicker/DatePicker.js";
10
11
  import { Input } from "../input/Input.js";
@@ -21,7 +22,7 @@ function FormFieldClient({
21
22
  onValidate,
22
23
  ...props
23
24
  }) {
24
- var _a, _b;
25
+ var _a, _b, _c;
25
26
  const renderFieldContainer = useCallback((children) => /* @__PURE__ */ jsx(GridRow, { className: bem(), xs: 12, children }), []);
26
27
  if (visible === false) return null;
27
28
  switch (fieldType) {
@@ -88,6 +89,26 @@ function FormFieldClient({
88
89
  }
89
90
  )
90
91
  );
92
+ case "dynamic-list":
93
+ const p = props;
94
+ return renderFieldContainer(
95
+ /* @__PURE__ */ jsx(
96
+ DynamicList,
97
+ {
98
+ priority: true,
99
+ ...p,
100
+ value: p == null ? void 0 : p.value,
101
+ fields: (_c = p == null ? void 0 : p.fields) == null ? void 0 : _c.map((field) => ({
102
+ ...field,
103
+ onValidate: /* @__PURE__ */ __name((_, err) => onValidate == null ? void 0 : onValidate(p, err), "onValidate")
104
+ })),
105
+ onChange: /* @__PURE__ */ __name((items) => onChange == null ? void 0 : onChange(
106
+ props,
107
+ items
108
+ ), "onChange")
109
+ }
110
+ )
111
+ );
91
112
  default:
92
113
  return null;
93
114
  }