@prokodo/ui 0.0.40 → 0.0.42

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 +6 -13
  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 +6 -1
  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
@@ -130,18 +130,8 @@ export default function GalleryPage() {
130
130
 
131
131
  ### Compatibility of the components
132
132
 
133
- ✅ = Available as RSC (<[ComponentName] />) and for client exportable (<[ComponentName]Client />)
134
- = Not available
135
- \- = Currently only for RSC optimized
136
-
137
- > If RSC and client have ✅-symbol means available as RSC (<[ComponentName] />) & extra client export (<[ComponentName]Client />)
138
-
139
- ## 📦 Available Components
140
-
141
- ### Compatibility of the components
142
-
143
- ✅ = Available as AIC (renders zero-JS RSC and self-hydrates when needed) and can also used as a client‐only entry.
144
- – = RSC (AIC) only; no client‐side bundle. (Best practice: Use it only in RSC)
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 needed. (Useable in both, but best practice to use in RSC only)
145
135
 
146
136
  | Component | ✅ AIC (RSC + optional client) | ✅ SSR-Compatible (`"use client"`) |
147
137
  |-----------------------|:--------------------------------:|:---------------------------------:|
@@ -158,6 +148,7 @@ export default function GalleryPage() {
158
148
  | DatePicker | ✅ | ✅ |
159
149
  | Dialog | ✅ | ✅ |
160
150
  | Drawer | ✅ | ✅ |
151
+ | DynamicList | ✅ | ✅ |
161
152
  | Form | ✅ | ✅ |
162
153
  | FormResponse | ✅ | – |
163
154
  | Grid/GridRow | ✅ | – |
@@ -176,12 +167,14 @@ export default function GalleryPage() {
176
167
  | PostTeaser | ❌ (Experimental - Coming soon) | – |
177
168
  | PostWidget | ❌ (Experimental - Coming soon) | – |
178
169
  | PostWidgetCarousel | ❌ (Experimental - Coming soon) | - |
170
+ | ProgressBar | ✅ | ✅ |
179
171
  | Quote | ✅ | – |
180
172
  | RichText | ✅ | ✅ |
181
173
  | Select | ✅ | ✅ |
182
174
  | SideNav | ✅ | ✅ |
183
175
  | Skeleton | ✅ | – |
184
176
  | Slider | ✅ | ✅ |
177
+ | Snackbar & Provider | ✅ | ✅ |
185
178
  | Stepper | ✅ | ✅ |
186
179
  | Switch | ✅ | ✅ |
187
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
  }
@@ -80,7 +80,12 @@ function DialogClient({ open = false, closeOnBackdropClick = true, onChange, ...
80
80
  }, "onMouseDown")
81
81
  },
82
82
  onClose: closeDialog,
83
- onMouseDown: /* @__PURE__ */ __name((e) => e.stopPropagation(), "onMouseDown")
83
+ onMouseDown: /* @__PURE__ */ __name((e) => e.stopPropagation(), "onMouseDown"),
84
+ onCloseKeyDown: /* @__PURE__ */ __name((e) => {
85
+ if (e.key === "Enter") {
86
+ closeDialog();
87
+ }
88
+ }, "onCloseKeyDown")
84
89
  }
85
90
  );
86
91
  }
@@ -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
  }