@parallelworks/ui 0.19.0 → 0.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (233) hide show
  1. package/README.md +1 -1
  2. package/dist/{chunks/memoryStore-CC91S5LP.js → ai/adapter/memoryStore.js} +2 -2
  3. package/dist/ai/adapter/mock/index.js +2 -80
  4. package/dist/ai/adapter/mock/mockAdapter.js +81 -0
  5. package/dist/ai/adapter/openai/createOpenAIStream.js +33 -0
  6. package/dist/ai/adapter/openai/errors.js +37 -0
  7. package/dist/ai/adapter/openai/index.js +5 -333
  8. package/dist/ai/adapter/openai/openaiAdapter.js +54 -0
  9. package/dist/ai/adapter/openai/responses.js +108 -0
  10. package/dist/ai/adapter/openai/sse.js +112 -0
  11. package/dist/{chunks/types-Yy0NrerF.js → ai/adapter/types.js} +1 -1
  12. package/dist/ai/agent/classifier.js +12 -0
  13. package/dist/ai/agent/diff.js +223 -0
  14. package/dist/ai/agent/diffHighlight.js +101 -0
  15. package/dist/ai/agent/permissions.js +29 -0
  16. package/dist/ai/agent/toolfmt.js +383 -0
  17. package/dist/ai/agent/transcript.js +127 -0
  18. package/dist/ai/components/AllocationSelector.js +56 -0
  19. package/dist/ai/components/AttachmentManager.js +147 -0
  20. package/dist/ai/components/AttachmentUpload.js +179 -0
  21. package/dist/ai/components/BlockedGroupBanner.js +29 -0
  22. package/dist/ai/components/BranchNavigator.js +57 -0
  23. package/dist/ai/components/ChatEmptyState.js +171 -0
  24. package/dist/ai/components/ChatInput.js +265 -0
  25. package/dist/ai/components/ChatLayout.js +15 -0
  26. package/dist/ai/components/ChatMessage.js +341 -0
  27. package/dist/ai/components/ChatMessageList.js +301 -0
  28. package/dist/ai/components/ChatSidebar.js +345 -0
  29. package/dist/ai/components/ChatThread.js +198 -0
  30. package/dist/ai/components/ComposerChrome.js +50 -0
  31. package/dist/ai/components/ComposerFrame.js +33 -0
  32. package/dist/ai/components/DragOverlay.js +20 -0
  33. package/dist/ai/components/ModelSelector.js +343 -0
  34. package/dist/ai/components/ShareDialog.js +260 -0
  35. package/dist/ai/components/SlashMenu.js +91 -0
  36. package/dist/ai/components/agent/ActivityLine.js +151 -0
  37. package/dist/ai/components/agent/AgentMessageParts.js +721 -0
  38. package/dist/ai/components/agent/PermissionPicker.js +38 -0
  39. package/dist/ai/components/attachmentKeys.js +10 -0
  40. package/dist/ai/core/ChatProvider.js +848 -0
  41. package/dist/ai/core/KeyboardShortcutsProvider.js +9 -0
  42. package/dist/ai/core/chatReducer.js +223 -0
  43. package/dist/ai/core/config.js +46 -0
  44. package/dist/ai/core/events.js +4 -0
  45. package/dist/ai/core/exportConversation.js +42 -0
  46. package/dist/ai/core/greeting.js +38 -0
  47. package/dist/ai/core/parts.js +84 -0
  48. package/dist/ai/core/useDragDrop.js +36 -0
  49. package/dist/ai/core/useKeyboardShortcuts.js +77 -0
  50. package/dist/ai/core/useSSEStream.js +98 -0
  51. package/dist/ai/index.js +43 -6644
  52. package/dist/ai/strings.js +175 -0
  53. package/dist/ai/ui/Avatar.js +35 -0
  54. package/dist/ai/ui/Dropdown.js +110 -0
  55. package/dist/ai/ui/Markdown.js +79 -0
  56. package/dist/ai/ui/Notice.js +77 -0
  57. package/dist/ai/ui/codeBreaks.js +36 -0
  58. package/dist/ai/ui/prose.js +13 -0
  59. package/dist/ai/ui/sidebar.js +148 -0
  60. package/dist/ai/utils.js +23 -0
  61. package/dist/assets/editor.worker-DfmPPyOL.js +60 -0
  62. package/dist/assets/json.worker-Dqgjpq9F.js +92 -0
  63. package/dist/assets/yaml.worker-DLx0whrM.js +1441 -0
  64. package/dist/components/AddMenu.js +46 -0
  65. package/dist/components/Avatar.js +46 -0
  66. package/dist/{chunks/BareModal-BtRiQezg.js → components/BareModal.js} +1 -1
  67. package/dist/components/Breadcrumbs.js +83 -0
  68. package/dist/components/Button.js +83 -0
  69. package/dist/components/Callout.js +23 -0
  70. package/dist/components/Card.js +31 -0
  71. package/dist/components/CollapsiblePanel.js +77 -0
  72. package/dist/{chunks/ConfirmModal-aOR4O1QE.js → components/ConfirmModal.js} +4 -9
  73. package/dist/components/CopyToClipboard.js +81 -0
  74. package/dist/{chunks/Markdown-CM-FenNE.js → components/CreateModal.js} +9 -116
  75. package/dist/components/DescriptionList.js +42 -0
  76. package/dist/components/Dropdown.js +349 -0
  77. package/dist/components/EmptyState.js +27 -0
  78. package/dist/components/Filter.js +32 -0
  79. package/dist/components/FilterPill.js +13 -0
  80. package/dist/components/IconButton.js +34 -0
  81. package/dist/{chunks/Indicator-hBSIxOPK.js → components/Indicator.js} +1 -1
  82. package/dist/components/Input.js +88 -0
  83. package/dist/components/LetterBadge.js +13 -0
  84. package/dist/components/Listbox.js +123 -0
  85. package/dist/{chunks/Loader-BXoXTZGc.js → components/Loader.js} +1 -1
  86. package/dist/components/Markdown.js +15 -0
  87. package/dist/components/MultiSelect.js +171 -0
  88. package/dist/components/Overview.js +39 -0
  89. package/dist/components/PageHeader.js +194 -0
  90. package/dist/components/Pagination.js +35 -0
  91. package/dist/{chunks/Provider-CDYurraE.js → components/Provider.js} +13 -5
  92. package/dist/{chunks/RequiredMark-DfLdYbYZ.js → components/RequiredMark.js} +1 -1
  93. package/dist/components/SectionHeader.js +11 -0
  94. package/dist/components/SettingModeOption.js +30 -0
  95. package/dist/components/SettingRow.js +35 -0
  96. package/dist/components/SettingsCard.js +31 -0
  97. package/dist/components/SettingsGroup.js +17 -0
  98. package/dist/components/Sort.js +42 -0
  99. package/dist/components/StatusBadge.js +63 -0
  100. package/dist/components/SwitchToggle.js +59 -0
  101. package/dist/{chunks/SwitchToggleSmall-FcsaYSTs.js → components/SwitchToggleSmall.js} +1 -1
  102. package/dist/{chunks/Table-DU2MW8xz.js → components/Table.js} +3 -3
  103. package/dist/components/Toggle.js +20 -0
  104. package/dist/{chunks/Tooltip-K5HJr4_p.js → components/Tooltip.js} +2 -27
  105. package/dist/{chunks/StatusBadge-C1Blx_cW.js → components/dropdownUtils.js} +2 -63
  106. package/dist/{chunks/focus-D_iZJTW1.js → components/focus.js} +1 -1
  107. package/dist/components/ghostButton.js +7 -0
  108. package/dist/components/inputClasses.js +4 -0
  109. package/dist/components/keys.js +27 -0
  110. package/dist/components/relativeTime.js +32 -0
  111. package/dist/{chunks/useCssIsDark-DHr05dG2.js → components/useCssIsDark.js} +1 -1
  112. package/dist/{chunks/duration-BOv8Phl8.js → duration.js} +1 -1
  113. package/dist/editor/Editor.js +13 -0
  114. package/dist/editor/EditorField.js +53 -0
  115. package/dist/editor/FormCodePanel.js +173 -0
  116. package/dist/{chunks/Monaco-DJ8MW-Dq.js → editor/Monaco.js} +5 -26
  117. package/dist/editor/index.js +6 -1
  118. package/dist/editor/themes.js +91 -0
  119. package/dist/editor/workers.d.ts +5 -0
  120. package/dist/editor/workers.js +35 -0
  121. package/dist/editor/yaml.d.ts +9 -1
  122. package/dist/editor/yaml.js +15 -0
  123. package/dist/editor/yaml.worker.d.ts +1 -0
  124. package/dist/editor/yamlLanguage.d.ts +6 -0
  125. package/dist/editor/yamlLanguage.js +312 -0
  126. package/dist/file-explorer/FileExplorer.js +1405 -0
  127. package/dist/file-explorer/FileExplorerContext.js +370 -0
  128. package/dist/{chunks/CodePreviewEditor-YqQBz1YL.js → file-explorer/FilePreview/CodePreviewEditor.js} +3 -2
  129. package/dist/file-explorer/FilePreview/Inline.js +45 -0
  130. package/dist/file-explorer/FilePreview/StreamedBadge.js +16 -0
  131. package/dist/file-explorer/FilePreview/Viewer.js +526 -0
  132. package/dist/file-explorer/FilePreview/index.js +266 -0
  133. package/dist/file-explorer/FilePreview/parse.js +63 -0
  134. package/dist/file-explorer/FilePreview/previewCache.js +98 -0
  135. package/dist/file-explorer/FilePreview/previewType.js +151 -0
  136. package/dist/file-explorer/FilePreview/readCappedBytes.js +196 -0
  137. package/dist/file-explorer/FilePreview/useObjectBlobUrl.js +95 -0
  138. package/dist/file-explorer/FilePreview/useObjectText.js +109 -0
  139. package/dist/file-explorer/FilePreview/usePresignedUrl.js +73 -0
  140. package/dist/file-explorer/FileRow.js +165 -0
  141. package/dist/file-explorer/FileRowsWindow.js +92 -0
  142. package/dist/file-explorer/FileTable.js +172 -0
  143. package/dist/file-explorer/FileTableHeaders.js +49 -0
  144. package/dist/file-explorer/LoadMoreRow.js +46 -0
  145. package/dist/file-explorer/TreeView.js +376 -0
  146. package/dist/file-explorer/helpers.js +537 -0
  147. package/dist/file-explorer/index.js +7 -5671
  148. package/dist/file-explorer/lib/batch.js +39 -0
  149. package/dist/file-explorer/lib/errors.js +9 -0
  150. package/dist/file-explorer/lib/paging.js +124 -0
  151. package/dist/file-explorer/lib/utils.js +322 -0
  152. package/dist/file-explorer/toasts.js +400 -0
  153. package/dist/file-explorer/treeRows.js +73 -0
  154. package/dist/file-explorer/useNearEnd.js +27 -0
  155. package/dist/form/FieldWrapper.js +54 -0
  156. package/dist/form/Fields/BooleanField.js +51 -0
  157. package/dist/form/Fields/CheckboxGroupField.js +72 -0
  158. package/dist/form/Fields/ColorField.js +33 -0
  159. package/dist/form/Fields/DropdownField.js +49 -0
  160. package/dist/form/Fields/DurationField.js +130 -0
  161. package/dist/form/Fields/LabelField.js +19 -0
  162. package/dist/form/Fields/MultiDropdownField.js +40 -0
  163. package/dist/form/Fields/NumberField.js +51 -0
  164. package/dist/form/Fields/ObjectField.js +54 -0
  165. package/dist/form/Fields/RadioField.js +49 -0
  166. package/dist/form/Fields/RangeField.js +58 -0
  167. package/dist/form/Fields/ResourceOptionIcon.js +21 -0
  168. package/dist/form/Fields/StepField.js +6 -0
  169. package/dist/form/Fields/StringField.js +37 -0
  170. package/dist/form/Fields/TextAreaField.js +31 -0
  171. package/dist/form/Fields/durationValidity.js +11 -0
  172. package/dist/form/Form.js +643 -0
  173. package/dist/form/SpecialTypes/DropdownWrapper.js +30 -0
  174. package/dist/form/SpecialTypes/FormikCustomDropdown.js +122 -0
  175. package/dist/form/SpecialTypes/FormikCustomInput.js +111 -0
  176. package/dist/form/SpecialTypes/FormikMultiSelectDropdown.js +31 -0
  177. package/dist/form/SpecialTypes/FormikNumericInput.js +60 -0
  178. package/dist/form/Wizard/WizardContainer.js +138 -0
  179. package/dist/form/Wizard/WizardNavigation.js +92 -0
  180. package/dist/form/Wizard/WizardStepContent.js +35 -0
  181. package/dist/form/Wizard/WizardStepIndicator.js +108 -0
  182. package/dist/form/Wizard/useWizardState.js +118 -0
  183. package/dist/form/Wizard/utils.js +34 -0
  184. package/dist/form/fieldContext.js +26 -0
  185. package/dist/form/fieldRegistry.js +50 -0
  186. package/dist/form/index.js +17 -2321
  187. package/dist/{chunks/FieldWrapper-Cszwg-4B.js → form/lib.js} +2 -97
  188. package/dist/form/useParsedOpts.js +62 -0
  189. package/dist/form/usePrevious.js +11 -0
  190. package/dist/form/utils/checkShowIfObject.js +14 -0
  191. package/dist/form/utils/duration.js +69 -0
  192. package/dist/form/utils/getParentValue.js +23 -0
  193. package/dist/form/utils/getPlaceholder.js +9 -0
  194. package/dist/form/utils/getValueUsingPath.js +23 -0
  195. package/dist/form/utils/secondaryField.js +22 -0
  196. package/dist/graph/AnnotationBanner.js +141 -0
  197. package/dist/graph/Collapse.js +41 -0
  198. package/dist/graph/DependencyGraph.js +1398 -0
  199. package/dist/graph/JobSummary.js +104 -0
  200. package/dist/graph/MatrixGroup.js +107 -0
  201. package/dist/graph/Reveal.js +57 -0
  202. package/dist/graph/TreeView.js +711 -0
  203. package/dist/graph/index.js +1 -2519
  204. package/dist/graph/types.js +6 -0
  205. package/dist/icons.d.ts +4 -4
  206. package/dist/icons.js +5 -5
  207. package/dist/index.js +46 -599
  208. package/dist/list/ActionToolbar.js +184 -0
  209. package/dist/list/HoverCard.js +73 -0
  210. package/dist/list/ListPage.js +145 -0
  211. package/dist/list/ListPager.js +59 -0
  212. package/dist/list/ListTable.js +163 -0
  213. package/dist/list/ListViewControls.js +372 -0
  214. package/dist/list/RowContextMenu.js +351 -0
  215. package/dist/list/UserHoverCard.js +117 -0
  216. package/dist/list/index.js +11 -2
  217. package/dist/list/listSearch.js +137 -0
  218. package/dist/list/listView.js +210 -0
  219. package/dist/list/textEntry.js +10 -0
  220. package/dist/{chunks/logviewer-BTKuQWzw.js → logviewer/LogViewer.js} +4 -82
  221. package/dist/logviewer/index.js +2 -1
  222. package/dist/logviewer/segments.js +80 -0
  223. package/dist/safeUrl.d.ts +6 -0
  224. package/dist/safeUrl.js +22 -0
  225. package/package.json +7 -9
  226. package/dist/assets/editor.worker-BmHUIVG4.js +0 -14807
  227. package/dist/assets/json.worker-D8bJ92nw.js +0 -22207
  228. package/dist/assets/yaml.worker-C4gyGAko.js +0 -50201
  229. package/dist/chunks/PageHeader-0kG_iypP.js +0 -692
  230. package/dist/chunks/SwitchToggle-DShNdcao.js +0 -758
  231. package/dist/chunks/editor-Dk1rbV75.js +0 -361
  232. package/dist/chunks/list-CJm875m7.js +0 -1418
  233. /package/dist/{chunks/MarkdownImpl-CyeTVvSt.js → components/MarkdownImpl.js} +0 -0
@@ -0,0 +1,123 @@
1
+ import { useStrings } from "./Provider.js";
2
+ import { AngleDownIcon } from "../icons.js";
3
+ import { keyedByContent } from "./keys.js";
4
+ import { focusOnMount } from "./focus.js";
5
+ import { Listbox, ListboxButton, ListboxOption, ListboxOptions, Transition } from "@headlessui/react";
6
+ import cx from "classnames";
7
+ import { useEffect, useRef, useState } from "react";
8
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
9
+ //#region src/components/Listbox.tsx
10
+ function CustomListbox({ options = [], handleOptionSelected, type, allowSearch = false, closeOnSelect = true, className = "", invalid = false, required = false, id, "aria-describedby": describedBy }) {
11
+ const { dropdown: strings } = useStrings();
12
+ const [filter, setFilter] = useState("");
13
+ const [controlledOpen, setControlledOpen] = useState(false);
14
+ const optionsToShow = options.filter((option) => !option.selected && option.label && option.label.toLowerCase().includes(filter.toLowerCase()));
15
+ function useOutsideAlerter(ref) {
16
+ useEffect(() => {
17
+ function handleClickOutside(event) {
18
+ if (ref.current && event.target instanceof Node && !ref.current.contains(event.target)) {
19
+ setControlledOpen(false);
20
+ setFilter("");
21
+ }
22
+ }
23
+ document.addEventListener("mousedown", handleClickOutside);
24
+ return () => {
25
+ document.removeEventListener("mousedown", handleClickOutside);
26
+ };
27
+ }, [ref]);
28
+ }
29
+ const wrapperRef = useRef(null);
30
+ useOutsideAlerter(wrapperRef);
31
+ const optionsElement = /* @__PURE__ */ jsxs(ListboxOptions, {
32
+ modal: false,
33
+ static: true,
34
+ className: "absolute w-full py-1 z-50 theme-input rounded-md",
35
+ children: [allowSearch && /* @__PURE__ */ jsx("div", {
36
+ className: "pl-2 pr-4 mb-1",
37
+ children: /* @__PURE__ */ jsx("input", {
38
+ autoComplete: "off",
39
+ type: "search",
40
+ ref: focusOnMount,
41
+ onChange: (e) => setFilter(e.target.value),
42
+ value: filter,
43
+ className: "w-full p-1 theme-input",
44
+ onKeyDown: (e) => {
45
+ if (![
46
+ "ArrowUp",
47
+ "ArrowDown",
48
+ "Enter",
49
+ "Home",
50
+ "End",
51
+ "Escape"
52
+ ].includes(e.key)) e.stopPropagation();
53
+ }
54
+ })
55
+ }), /* @__PURE__ */ jsx("div", {
56
+ className: "overflow-auto max-h-60 theme-panel",
57
+ children: optionsToShow.length > 0 ? keyedByContent(optionsToShow, (o) => String(o.value)).map(({ key, item: option }) => /* @__PURE__ */ jsx(ListboxOption, {
58
+ className: "relative hover:theme-hover select-none pl-2 pr-4",
59
+ value: option.value,
60
+ children: /* @__PURE__ */ jsx("div", {
61
+ className: "w-full flex flex-row",
62
+ children: /* @__PURE__ */ jsxs("div", {
63
+ className: "w-3/4 py-2 flex items-center",
64
+ children: [
65
+ /* @__PURE__ */ jsx("div", {
66
+ className: "w-4 h-6 btn btn-info text-xl line-height-0 mr-2",
67
+ children: "+"
68
+ }),
69
+ option.icon && /* @__PURE__ */ jsx("span", {
70
+ className: "mr-2 flex items-center",
71
+ children: option.icon
72
+ }),
73
+ /* @__PURE__ */ jsx("span", {
74
+ className: "mr-2",
75
+ children: option.label
76
+ }),
77
+ /* @__PURE__ */ jsx("span", {
78
+ className: "italic",
79
+ children: option.secondaryLabel
80
+ })
81
+ ]
82
+ })
83
+ })
84
+ }, key)) : /* @__PURE__ */ jsx("div", {
85
+ className: "w-full flex flex-row",
86
+ children: /* @__PURE__ */ jsx("div", {
87
+ className: "w-3/4 py-2 pl-2 capitalize flex items-center",
88
+ children: filter === "" ? `All ${type} Added` : `No ${type} Found`
89
+ })
90
+ })
91
+ })]
92
+ });
93
+ return /* @__PURE__ */ jsxs(Listbox, {
94
+ as: "div",
95
+ className: cx("relative mt-1 theme-input border theme-border rounded-md", className),
96
+ ref: wrapperRef,
97
+ onChange: handleOptionSelected,
98
+ children: [/* @__PURE__ */ jsxs(ListboxButton, {
99
+ id,
100
+ "aria-describedby": describedBy,
101
+ "aria-required": required || void 0,
102
+ onClick: () => setControlledOpen((prev) => !prev),
103
+ className: cx("relative w-full py-2 pl-3 text-left", invalid && "border-red-600 focus:border-red-600 focus:ring-red-500"),
104
+ children: [/* @__PURE__ */ jsx("span", {
105
+ className: "block truncate",
106
+ children: strings.select(type)
107
+ }), /* @__PURE__ */ jsx("span", {
108
+ className: "pointer-events-none absolute inset-y-0 right-0 flex items-center justify-items-center",
109
+ children: /* @__PURE__ */ jsx(AngleDownIcon, {
110
+ className: "h-5 w-8",
111
+ "aria-hidden": "true"
112
+ })
113
+ })]
114
+ }), closeOnSelect ? /* @__PURE__ */ jsx(Transition, {
115
+ leave: "transition ease-in duration-100",
116
+ leaveFrom: "opacity-100",
117
+ leaveTo: "opacity-0",
118
+ children: optionsElement || null
119
+ }) : /* @__PURE__ */ jsx(Fragment$1, { children: controlledOpen && optionsElement })]
120
+ });
121
+ }
122
+ //#endregion
123
+ export { CustomListbox as default };
@@ -44,4 +44,4 @@ function Loader({ size = 48, text, textSize = 12, full = true, color = "", loade
44
44
  });
45
45
  }
46
46
  //#endregion
47
- export { Loader as t };
47
+ export { Loader as default };
@@ -0,0 +1,15 @@
1
+ import { Suspense, lazy } from "react";
2
+ import { jsx } from "react/jsx-runtime";
3
+ //#region src/components/Markdown.tsx
4
+ var MarkdownImpl = lazy(() => import("./MarkdownImpl.js"));
5
+ function Markdown(props) {
6
+ return /* @__PURE__ */ jsx(Suspense, {
7
+ fallback: /* @__PURE__ */ jsx("div", {
8
+ className: "markdown whitespace-pre-wrap text-start w-full",
9
+ children: props.children
10
+ }),
11
+ children: /* @__PURE__ */ jsx(MarkdownImpl, { ...props })
12
+ });
13
+ }
14
+ //#endregion
15
+ export { Markdown as default };
@@ -0,0 +1,171 @@
1
+ import { useStrings } from "./Provider.js";
2
+ import { keyedByContent } from "./keys.js";
3
+ import { DropdownCaret, filterOption, flattenOptions, isCategory, isOption } from "./dropdownUtils.js";
4
+ import { focusOnMount } from "./focus.js";
5
+ import { Combobox, ComboboxButton, ComboboxOption, ComboboxOptions } from "@headlessui/react";
6
+ import cx from "classnames";
7
+ import { useCallback, useMemo, useState } from "react";
8
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
9
+ import { usePopper } from "react-popper";
10
+ //#region src/components/MultiSelect.tsx
11
+ function MultiSelectDropdown({ options, value, onChange, id, "aria-labelledby": labelledBy, "aria-describedby": describedBy, required, className, wrapperClassName = "w-full", textBoxClassName, disabled = false, placeholder, loading = false, searchable = true, maxTagCount = 2, compareBy }) {
12
+ const strings = useStrings();
13
+ const [query, setQuery] = useState("");
14
+ const [referenceEl, setReferenceEl] = useState(null);
15
+ const [popperEl, setPopperEl] = useState(null);
16
+ const { styles, attributes } = usePopper(referenceEl, popperEl, {
17
+ placement: "bottom-start",
18
+ modifiers: [{
19
+ name: "offset",
20
+ options: { offset: [0, 4] }
21
+ }]
22
+ });
23
+ const allOptions = useMemo(() => flattenOptions(options), [options]);
24
+ const compare = compareBy ?? ((a, b) => a === b);
25
+ const selectedOptions = useMemo(() => {
26
+ const result = [];
27
+ for (const val of value) {
28
+ const found = allOptions.find((opt) => isOption(opt) && compare(opt.value, val));
29
+ if (found) result.push(found);
30
+ }
31
+ return result;
32
+ }, [
33
+ value,
34
+ allOptions,
35
+ compare
36
+ ]);
37
+ const filteredOptions = useMemo(() => {
38
+ if (!searchable || query.trim() === "") return allOptions;
39
+ const result = [];
40
+ for (const opt of allOptions) if (isCategory(opt)) {
41
+ const matchedChildren = (Array.isArray(opt.options) ? opt.options : []).filter((o) => filterOption(o, query));
42
+ if (matchedChildren.length > 0) result.push(opt, ...matchedChildren);
43
+ } else if (isOption(opt) && filterOption(opt, query)) result.push(opt);
44
+ return result;
45
+ }, [
46
+ allOptions,
47
+ query,
48
+ searchable
49
+ ]);
50
+ const display = useMemo(() => {
51
+ const shown = selectedOptions.slice(0, maxTagCount);
52
+ return {
53
+ label: shown.map((o) => o.label).join(", "),
54
+ overflow: selectedOptions.length - shown.length
55
+ };
56
+ }, [selectedOptions, maxTagCount]);
57
+ const handleChange = useCallback((newValues) => {
58
+ if (!Array.isArray(newValues)) return;
59
+ onChange(newValues);
60
+ }, [onChange]);
61
+ const isDisabled = disabled || loading;
62
+ const isEmpty = filteredOptions.length === 0;
63
+ return /* @__PURE__ */ jsx(Combobox, {
64
+ multiple: true,
65
+ value: Array.isArray(value) ? value : [],
66
+ onChange: handleChange,
67
+ disabled: isDisabled,
68
+ onClose: () => setQuery(""),
69
+ by: compare,
70
+ children: ({ open }) => /* @__PURE__ */ jsxs("div", {
71
+ ref: setReferenceEl,
72
+ className: cx("relative", wrapperClassName),
73
+ children: [
74
+ /* @__PURE__ */ jsx(ComboboxButton, {
75
+ as: "div",
76
+ id,
77
+ "aria-labelledby": labelledBy,
78
+ "aria-describedby": describedBy,
79
+ "aria-required": required || void 0,
80
+ className: cx("theme-input flex items-center cursor-pointer rounded border text-[14px] w-full px-2 pr-8 py-1 min-h-[30px] overflow-hidden", isDisabled && "opacity-50 cursor-not-allowed", textBoxClassName, className),
81
+ children: loading ? /* @__PURE__ */ jsx("span", {
82
+ className: "theme-muted-text",
83
+ children: strings.loading
84
+ }) : selectedOptions.length > 0 ? /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("span", {
85
+ className: "min-w-0 truncate",
86
+ children: display.label
87
+ }), display.overflow > 0 && /* @__PURE__ */ jsxs("span", {
88
+ className: "ml-1 shrink-0 theme-muted-text",
89
+ children: ["+", display.overflow]
90
+ })] }) : /* @__PURE__ */ jsx("span", {
91
+ className: "theme-muted-text truncate",
92
+ children: placeholder
93
+ })
94
+ }),
95
+ /* @__PURE__ */ jsx(DropdownCaret, {}),
96
+ open && /* @__PURE__ */ jsxs(ComboboxOptions, {
97
+ modal: false,
98
+ ref: setPopperEl,
99
+ static: true,
100
+ "data-testid": "msd-list",
101
+ style: styles["popper"],
102
+ ...attributes["popper"],
103
+ className: "theme-panel z-10 max-h-60 w-full overflow-auto rounded-md shadow-lg focus:outline-none",
104
+ children: [searchable && /* @__PURE__ */ jsx("div", {
105
+ className: "sticky top-0 theme-panel p-2 border-b z-10",
106
+ children: /* @__PURE__ */ jsx("input", {
107
+ placeholder,
108
+ "data-1p-ignore": true,
109
+ autoComplete: "off",
110
+ type: "text",
111
+ className: "theme-input w-full",
112
+ value: query,
113
+ onChange: (e) => setQuery(e.target.value),
114
+ onKeyDown: (e) => e.stopPropagation(),
115
+ ref: focusOnMount
116
+ })
117
+ }), /* @__PURE__ */ jsx("div", {
118
+ className: "py-1",
119
+ children: isEmpty ? /* @__PURE__ */ jsx("div", {
120
+ className: "px-4 py-2 text-sm theme-muted-text",
121
+ children: strings.dropdown.noOptionsFound
122
+ }) : keyedByContent(filteredOptions, (o) => isCategory(o) ? `category-${o.category ?? "uncat"}` : `option-${String(o.value)}`).map(({ key, item: opt }) => {
123
+ if (isCategory(opt)) return /* @__PURE__ */ jsx("li", {
124
+ role: "presentation",
125
+ className: "px-4 py-2 text-sm font-bold theme-muted-text",
126
+ children: opt.category
127
+ }, key);
128
+ const option = opt;
129
+ return /* @__PURE__ */ jsx(ComboboxOption, {
130
+ value: option.value,
131
+ disabled: option.disabled ?? false,
132
+ "data-testid": `msd-option-${String(option.value)}`,
133
+ className: ({ focus }) => cx("relative cursor-pointer select-none py-2 pl-10 pr-4 text-sm", focus && "theme-hover", option.disabled && "cursor-not-allowed opacity-50"),
134
+ children: ({ selected }) => /* @__PURE__ */ jsxs("div", {
135
+ className: "flex items-center",
136
+ children: [
137
+ /* @__PURE__ */ jsx("span", {
138
+ className: "absolute inset-y-0 left-0 flex items-center pl-3",
139
+ children: /* @__PURE__ */ jsx("input", {
140
+ autoComplete: "off",
141
+ type: "checkbox",
142
+ checked: selected,
143
+ readOnly: true,
144
+ tabIndex: -1,
145
+ className: "h-4 w-4 cursor-pointer",
146
+ "aria-hidden": "true"
147
+ })
148
+ }),
149
+ option.icon && /* @__PURE__ */ jsx("span", {
150
+ className: "mr-2 flex items-center",
151
+ children: option.icon
152
+ }),
153
+ /* @__PURE__ */ jsx("div", {
154
+ className: "flex flex-col",
155
+ children: /* @__PURE__ */ jsx("span", {
156
+ className: "block truncate",
157
+ children: option.label
158
+ })
159
+ })
160
+ ]
161
+ })
162
+ }, key);
163
+ })
164
+ })]
165
+ })
166
+ ]
167
+ })
168
+ });
169
+ }
170
+ //#endregion
171
+ export { MultiSelectDropdown as default };
@@ -0,0 +1,39 @@
1
+ import cx from "classnames";
2
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
+ import Skeleton from "react-loading-skeleton";
4
+ //#region src/components/Overview.tsx
5
+ function Overview({ Icon, name, type, children, right, className, loading, iconSize = 75 }) {
6
+ return /* @__PURE__ */ jsxs("div", {
7
+ className: cx("flex items-center w-full", className),
8
+ children: [
9
+ loading ? /* @__PURE__ */ jsx(Skeleton, {
10
+ width: iconSize,
11
+ height: iconSize,
12
+ circle: true
13
+ }) : Icon,
14
+ /* @__PURE__ */ jsx("div", {
15
+ className: "flex flex-col min-w-0 flex-1",
16
+ children: loading ? /* @__PURE__ */ jsx(Skeleton, {
17
+ count: 2,
18
+ height: 12
19
+ }) : /* @__PURE__ */ jsxs(Fragment, { children: [
20
+ /* @__PURE__ */ jsx("div", {
21
+ className: "font-semibold text-xl tracking-tight",
22
+ children: name
23
+ }),
24
+ type && /* @__PURE__ */ jsx("p", { children: type }),
25
+ /* @__PURE__ */ jsx("div", {
26
+ className: "flex flex-row gap-x-2",
27
+ children
28
+ })
29
+ ] })
30
+ }),
31
+ right && /* @__PURE__ */ jsx("div", {
32
+ className: "shrink-0 self-center",
33
+ children: right
34
+ })
35
+ ]
36
+ });
37
+ }
38
+ //#endregion
39
+ export { Overview };
@@ -0,0 +1,194 @@
1
+ import { useLink, useSlots, useStrings } from "./Provider.js";
2
+ import { AddIcon, ChevronRightIcon, EditIcon, MoreIcon } from "../icons.js";
3
+ import { keyedByContent } from "./keys.js";
4
+ import { TOOLTIP_ID } from "./Tooltip.js";
5
+ import { AddMenu } from "./AddMenu.js";
6
+ import { useBreadcrumb } from "./Breadcrumbs.js";
7
+ import { useRowMenu } from "../list/RowContextMenu.js";
8
+ import cx from "classnames";
9
+ import { Fragment, useLayoutEffect } from "react";
10
+ import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
11
+ import { createPortal } from "react-dom";
12
+ //#region src/components/PageHeader.tsx
13
+ var headerActionButtonClasses = "flex items-center justify-center w-6 h-6 rounded-md shrink-0 cursor-pointer text-(--theme-muted-text-color) hover:text-(--theme-app) hover:bg-(--theme-muted-panel-bg) transition-colors";
14
+ var headerAddButtonClasses = "inline-flex h-[26px] shrink-0 items-center gap-1.5 rounded-md border border-(--theme-border) px-2 text-xs font-medium cursor-pointer text-(--theme-muted-text-color) hover:bg-(--theme-muted-panel-bg) hover:text-(--theme-app) transition-colors";
15
+ /** With menu, the plus opens a chooser; otherwise navigates to or calls the
16
+ * single action. `word` is the visible verb; `label` stays the full action for
17
+ * the tooltip and screen readers. */
18
+ function HeaderAddButton({ to, onClick, label, word = "add", menu, disabled = false, disabledHint }) {
19
+ const { common } = useStrings();
20
+ const Link = useLink();
21
+ const content = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(AddIcon, { className: "w-3 h-3" }), /* @__PURE__ */ jsx("span", { children: word === "create" ? common.create : common.add })] });
22
+ if (menu) return /* @__PURE__ */ jsx(AddMenu, {
23
+ items: menu,
24
+ label,
25
+ buttonClassName: headerAddButtonClasses,
26
+ children: content
27
+ });
28
+ if (to) return /* @__PURE__ */ jsx(Link, {
29
+ to,
30
+ "aria-label": label,
31
+ title: label,
32
+ className: headerAddButtonClasses,
33
+ children: content
34
+ });
35
+ const hint = disabled ? disabledHint : void 0;
36
+ return /* @__PURE__ */ jsx("button", {
37
+ type: "button",
38
+ onClick: disabled ? void 0 : onClick,
39
+ "aria-label": hint ? `${label}. ${hint}` : label,
40
+ "aria-disabled": disabled || void 0,
41
+ ...hint ? {
42
+ "data-tooltip-id": TOOLTIP_ID,
43
+ "data-tooltip-content": hint
44
+ } : { title: label },
45
+ className: cx(headerAddButtonClasses, "aria-disabled:cursor-not-allowed aria-disabled:opacity-50 aria-disabled:hover:bg-transparent aria-disabled:hover:text-(--theme-muted-text-color)"),
46
+ children: content
47
+ });
48
+ }
49
+ function HeaderActionMenu({ items, label = "Actions" }) {
50
+ if (items.length === 0) return null;
51
+ return /* @__PURE__ */ jsx(AddMenu, {
52
+ items,
53
+ label,
54
+ buttonClassName: headerActionButtonClasses,
55
+ children: /* @__PURE__ */ jsx(MoreIcon, { className: "w-3.5 h-3.5" })
56
+ });
57
+ }
58
+ /** The header "…" trigger for a RowMenuItem menu — same rendering (submenus,
59
+ * destructive styling) as the list pages' right-click context menus. */
60
+ function HeaderRowMenu({ items, label = "Actions" }) {
61
+ const { openMenu, contextMenu } = useRowMenu();
62
+ if (items.length === 0) return null;
63
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx("button", {
64
+ type: "button",
65
+ "aria-label": label,
66
+ title: label,
67
+ className: headerActionButtonClasses,
68
+ onClick: (e) => {
69
+ const r = e.currentTarget.getBoundingClientRect();
70
+ openMenu(r.left, r.bottom + 4, items);
71
+ },
72
+ children: /* @__PURE__ */ jsx(MoreIcon, { className: "w-3.5 h-3.5" })
73
+ }), contextMenu] });
74
+ }
75
+ function HeaderEditButton({ to, onClick, label = "Edit", disabled, tooltip }) {
76
+ const Link = useLink();
77
+ const tooltipProps = tooltip ? {
78
+ "data-tooltip-id": TOOLTIP_ID,
79
+ "data-tooltip-content": tooltip
80
+ } : {};
81
+ if (to && !disabled) return /* @__PURE__ */ jsx(Link, {
82
+ to,
83
+ "aria-label": label,
84
+ ...tooltip ? {} : { title: label },
85
+ className: headerActionButtonClasses,
86
+ ...tooltipProps,
87
+ children: /* @__PURE__ */ jsx(EditIcon, { className: "w-3 h-3" })
88
+ });
89
+ return /* @__PURE__ */ jsx("button", {
90
+ type: "button",
91
+ onClick,
92
+ disabled,
93
+ "aria-label": label,
94
+ title: tooltip ? void 0 : label,
95
+ className: cx(headerActionButtonClasses, disabled && "opacity-50 cursor-not-allowed hover:bg-transparent"),
96
+ ...tooltipProps,
97
+ children: /* @__PURE__ */ jsx(EditIcon, { className: "w-3 h-3" })
98
+ });
99
+ }
100
+ /** Renders nothing when the modern breadcrumb strip isn't mounted (classic chrome or self-headered pages). */
101
+ function BreadcrumbsTitleAction({ children }) {
102
+ const { titleActionSlot } = useBreadcrumb();
103
+ if (!titleActionSlot) return null;
104
+ return createPortal(children, titleActionSlot);
105
+ }
106
+ function BreadcrumbsRightAction({ children }) {
107
+ const { rightActionSlot } = useBreadcrumb();
108
+ if (!rightActionSlot) return null;
109
+ return createPortal(children, rightActionSlot);
110
+ }
111
+ var breadcrumbsActionClasses = "flex items-center gap-1 link text-xs whitespace-nowrap disabled:opacity-50 disabled:cursor-not-allowed";
112
+ function BreadcrumbsActionButton({ icon: Icon, label, ariaLabel, to, onClick, disabled, tooltip }) {
113
+ const Link = useLink();
114
+ const tip = tooltip ? {
115
+ "data-tooltip-id": TOOLTIP_ID,
116
+ "data-tooltip-content": tooltip
117
+ } : {};
118
+ const content = /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(Icon, { className: "w-3 h-3" }), label] });
119
+ if (to && !disabled) return /* @__PURE__ */ jsx(Link, {
120
+ to,
121
+ className: breadcrumbsActionClasses,
122
+ ...ariaLabel ? { "aria-label": ariaLabel } : {},
123
+ ...tip,
124
+ children: content
125
+ });
126
+ return /* @__PURE__ */ jsx("button", {
127
+ type: "button",
128
+ onClick,
129
+ disabled,
130
+ className: breadcrumbsActionClasses,
131
+ ...ariaLabel ? { "aria-label": ariaLabel } : {},
132
+ ...tip,
133
+ children: content
134
+ });
135
+ }
136
+ function PageHeader({ breadcrumbs, title, titleAction, actions, toolbar, className, sticky = true, stickyTopClassName = "top-0" }) {
137
+ const { setHidden } = useBreadcrumb();
138
+ const Link = useLink();
139
+ const { breadcrumbPin, navToggle } = useSlots();
140
+ useLayoutEffect(() => {
141
+ setHidden(true);
142
+ return () => setHidden(false);
143
+ }, [setHidden]);
144
+ const crumbs = [...breadcrumbs ?? []];
145
+ const lastLabel = crumbs[crumbs.length - 1]?.label;
146
+ if (title !== null && title !== void 0 && title !== lastLabel) crumbs.push({ label: title });
147
+ const crumbRow = crumbs.length > 0 && /* @__PURE__ */ jsxs("div", {
148
+ className: "flex items-center gap-1.5 min-w-0",
149
+ children: [
150
+ /* @__PURE__ */ jsx("nav", {
151
+ "aria-label": "Breadcrumb",
152
+ className: "flex items-center gap-2 min-w-0 text-[13px]",
153
+ children: keyedByContent(crumbs, (c) => c.href ?? (typeof c.label === "string" ? c.label : "crumb")).map(({ key, item: crumb }, idx) => {
154
+ if (idx === crumbs.length - 1) return /* @__PURE__ */ jsx("h1", {
155
+ className: "m-0 text-[13px] font-medium leading-none text-(--theme-app) truncate",
156
+ children: crumb.label
157
+ }, key);
158
+ return /* @__PURE__ */ jsxs(Fragment, { children: [crumb.href ? /* @__PURE__ */ jsx(Link, {
159
+ to: crumb.href,
160
+ className: "text-(--theme-muted-text-color) hover:text-(--theme-app) transition-colors cursor-pointer whitespace-nowrap",
161
+ children: crumb.label
162
+ }) : /* @__PURE__ */ jsx("span", {
163
+ className: "text-(--theme-muted-text-color) whitespace-nowrap",
164
+ children: crumb.label
165
+ }), /* @__PURE__ */ jsx(ChevronRightIcon, { className: "w-3 h-3 opacity-60 shrink-0 text-(--theme-muted-text-color)" })] }, key);
166
+ })
167
+ }),
168
+ titleAction,
169
+ breadcrumbPin?.({ crumbs })
170
+ ]
171
+ });
172
+ const actionCluster = actions && /* @__PURE__ */ jsx("div", {
173
+ className: "flex items-center gap-1.5 shrink-0",
174
+ children: actions
175
+ });
176
+ const toggle = navToggle?.();
177
+ const hasLeading = !!crumbRow || !!toggle;
178
+ const leading = hasLeading ? /* @__PURE__ */ jsxs("div", {
179
+ className: "flex items-center gap-2 min-w-0",
180
+ children: [toggle, crumbRow]
181
+ }) : /* @__PURE__ */ jsx("div", {});
182
+ return /* @__PURE__ */ jsxs("div", {
183
+ className: cx(sticky && cx("sticky z-20", stickyTopClassName), "w-full bg-(--theme-app-bg)", className),
184
+ children: [/* @__PURE__ */ jsxs("div", {
185
+ className: cx("flex items-center justify-between gap-6 px-4 h-11", hasLeading && "border-b border-(--theme-border)"),
186
+ children: [leading, actionCluster]
187
+ }), toolbar && /* @__PURE__ */ jsx("div", {
188
+ className: "px-4",
189
+ children: toolbar
190
+ })]
191
+ });
192
+ }
193
+ //#endregion
194
+ export { BreadcrumbsActionButton, BreadcrumbsRightAction, BreadcrumbsTitleAction, HeaderActionMenu, HeaderAddButton, HeaderEditButton, HeaderRowMenu, PageHeader, headerActionButtonClasses };
@@ -0,0 +1,35 @@
1
+ import { useStrings } from "./Provider.js";
2
+ import cx from "classnames";
3
+ import { jsx, jsxs } from "react/jsx-runtime";
4
+ //#region src/components/Pagination.tsx
5
+ function Pagination({ endingNumber, endingTime, nextCallback, prevCallback, roundedBottom, startingNumber, startingTime, nextDisabled, prevDisabled, name, useTimeRange = false }) {
6
+ const t = useStrings().list;
7
+ return /* @__PURE__ */ jsxs("nav", {
8
+ className: cx(roundedBottom && "rounded-b-2xl", "theme-muted-panel flex items-center justify-between border-t theme-border px-4 py-1 sm:px-6"),
9
+ "aria-label": "Pagination",
10
+ children: [/* @__PURE__ */ jsx("div", {
11
+ className: cx("hidden", (startingNumber !== void 0 && startingNumber !== null && endingNumber !== void 0 && endingNumber !== null || startingTime && endingTime) && "sm:block"),
12
+ children: /* @__PURE__ */ jsx("p", {
13
+ className: "text-sm whitespace-nowrap",
14
+ children: useTimeRange && startingTime && endingTime ? t.paginationShowingTimeRange(name ?? "", startingTime, endingTime) : t.paginationShowing(name ?? "", startingNumber ?? "", endingNumber ?? "")
15
+ })
16
+ }), /* @__PURE__ */ jsxs("div", {
17
+ className: "flex flex-1 justify-between sm:justify-end gap-x-2",
18
+ children: [/* @__PURE__ */ jsx("button", {
19
+ type: "button",
20
+ disabled: prevDisabled,
21
+ onClick: prevCallback,
22
+ className: cx("link text-sm", prevDisabled && "disabled"),
23
+ children: t.paginationPrevious
24
+ }), /* @__PURE__ */ jsx("button", {
25
+ type: "button",
26
+ disabled: nextDisabled,
27
+ onClick: nextCallback,
28
+ className: cx("link text-sm", nextDisabled && "disabled"),
29
+ children: t.paginationNext
30
+ })]
31
+ })]
32
+ });
33
+ }
34
+ //#endregion
35
+ export { Pagination };
@@ -1,9 +1,10 @@
1
+ import { safeUrl } from "../safeUrl.js";
1
2
  import { createContext, use, useCallback, useContext, useEffect, useMemo } from "react";
2
3
  import { useLocalStorage } from "usehooks-ts";
3
4
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
4
5
  //#region src/components/Provider.tsx
5
6
  var DefaultLink = ({ to, onClick, className, children, ...rest }) => /* @__PURE__ */ jsx("a", {
6
- href: to,
7
+ href: safeUrl(to),
7
8
  onClick,
8
9
  className,
9
10
  ...rest,
@@ -399,11 +400,18 @@ var DEFAULTS = {
399
400
  }
400
401
  },
401
402
  navigation: {
402
- goTo: (to) => window.location.assign(to),
403
+ goTo: (to) => {
404
+ const url = safeUrl(to);
405
+ if (url) window.location.assign(url);
406
+ },
403
407
  openStepSource: (_uses, sourceUrl) => {
404
- if (sourceUrl) window.open(sourceUrl, "_blank");
408
+ const url = safeUrl(sourceUrl);
409
+ if (url) window.open(url, "_blank");
405
410
  },
406
- openExternal: (href) => window.open(href, "_blank")
411
+ openExternal: (href) => {
412
+ const url = safeUrl(href);
413
+ if (url) window.open(url, "_blank");
414
+ }
407
415
  },
408
416
  data: {
409
417
  useRunFile: defaultUseRunFile,
@@ -548,4 +556,4 @@ function UIProvider({ notify, strings, navigation, data, slots, engine, children
548
556
  });
549
557
  }
550
558
  //#endregion
551
- export { useOptionalWorkflowEngine as a, useRunFile as c, useWorkflowEngine as d, useWorkflowEngineLoader as f, useNotify as i, useSlots as l, useLink as n, usePersistedState as o, useNavigation as r, useProvisionCorsRules as s, UIProvider as t, useStrings as u };
559
+ export { UIProvider, useLink, useNavigation, useNotify, useOptionalWorkflowEngine, usePersistedState, useProvisionCorsRules, useRunFile, useSlots, useStrings, useWorkflowEngine, useWorkflowEngineLoader };
@@ -8,4 +8,4 @@ function RequiredMark() {
8
8
  });
9
9
  }
10
10
  //#endregion
11
- export { RequiredMark as t };
11
+ export { RequiredMark };
@@ -0,0 +1,11 @@
1
+ import cx from "classnames";
2
+ import { jsx } from "react/jsx-runtime";
3
+ //#region src/components/SectionHeader.tsx
4
+ function SectionHeader({ children, className = "", size = "md" }) {
5
+ return /* @__PURE__ */ jsx("div", {
6
+ className: cx("w-full font-semibold", size === "sm" ? "mb-2 text-sm theme-text" : "text-lg", className),
7
+ children
8
+ });
9
+ }
10
+ //#endregion
11
+ export { SectionHeader as default };