@parallelworks/ui 0.19.0 → 0.19.1

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 (217) hide show
  1. package/dist/{chunks/memoryStore-CC91S5LP.js → ai/adapter/memoryStore.js} +2 -2
  2. package/dist/ai/adapter/mock/index.js +2 -80
  3. package/dist/ai/adapter/mock/mockAdapter.js +81 -0
  4. package/dist/ai/adapter/openai/createOpenAIStream.js +33 -0
  5. package/dist/ai/adapter/openai/errors.js +37 -0
  6. package/dist/ai/adapter/openai/index.js +5 -333
  7. package/dist/ai/adapter/openai/openaiAdapter.js +54 -0
  8. package/dist/ai/adapter/openai/responses.js +108 -0
  9. package/dist/ai/adapter/openai/sse.js +112 -0
  10. package/dist/{chunks/types-Yy0NrerF.js → ai/adapter/types.js} +1 -1
  11. package/dist/ai/agent/classifier.js +12 -0
  12. package/dist/ai/agent/diff.js +223 -0
  13. package/dist/ai/agent/diffHighlight.js +101 -0
  14. package/dist/ai/agent/permissions.js +29 -0
  15. package/dist/ai/agent/toolfmt.js +383 -0
  16. package/dist/ai/agent/transcript.js +127 -0
  17. package/dist/ai/components/AllocationSelector.js +56 -0
  18. package/dist/ai/components/AttachmentManager.js +144 -0
  19. package/dist/ai/components/AttachmentUpload.js +179 -0
  20. package/dist/ai/components/BlockedGroupBanner.js +29 -0
  21. package/dist/ai/components/BranchNavigator.js +57 -0
  22. package/dist/ai/components/ChatEmptyState.js +171 -0
  23. package/dist/ai/components/ChatInput.js +265 -0
  24. package/dist/ai/components/ChatLayout.js +15 -0
  25. package/dist/ai/components/ChatMessage.js +338 -0
  26. package/dist/ai/components/ChatMessageList.js +301 -0
  27. package/dist/ai/components/ChatSidebar.js +345 -0
  28. package/dist/ai/components/ChatThread.js +198 -0
  29. package/dist/ai/components/ComposerChrome.js +50 -0
  30. package/dist/ai/components/ComposerFrame.js +33 -0
  31. package/dist/ai/components/DragOverlay.js +20 -0
  32. package/dist/ai/components/ModelSelector.js +343 -0
  33. package/dist/ai/components/ShareDialog.js +260 -0
  34. package/dist/ai/components/SlashMenu.js +91 -0
  35. package/dist/ai/components/agent/ActivityLine.js +151 -0
  36. package/dist/ai/components/agent/AgentMessageParts.js +721 -0
  37. package/dist/ai/components/agent/PermissionPicker.js +38 -0
  38. package/dist/ai/components/attachmentKeys.js +10 -0
  39. package/dist/ai/core/ChatProvider.js +848 -0
  40. package/dist/ai/core/KeyboardShortcutsProvider.js +9 -0
  41. package/dist/ai/core/chatReducer.js +223 -0
  42. package/dist/ai/core/config.js +45 -0
  43. package/dist/ai/core/events.js +4 -0
  44. package/dist/ai/core/exportConversation.js +42 -0
  45. package/dist/ai/core/greeting.js +38 -0
  46. package/dist/ai/core/parts.js +84 -0
  47. package/dist/ai/core/useDragDrop.js +36 -0
  48. package/dist/ai/core/useKeyboardShortcuts.js +77 -0
  49. package/dist/ai/core/useSSEStream.js +98 -0
  50. package/dist/ai/index.js +43 -6644
  51. package/dist/ai/strings.js +175 -0
  52. package/dist/ai/ui/Avatar.js +35 -0
  53. package/dist/ai/ui/Dropdown.js +110 -0
  54. package/dist/ai/ui/Markdown.js +79 -0
  55. package/dist/ai/ui/Notice.js +77 -0
  56. package/dist/ai/ui/codeBreaks.js +36 -0
  57. package/dist/ai/ui/prose.js +13 -0
  58. package/dist/ai/ui/sidebar.js +148 -0
  59. package/dist/ai/utils.js +23 -0
  60. package/dist/components/AddMenu.js +46 -0
  61. package/dist/components/Avatar.js +46 -0
  62. package/dist/{chunks/BareModal-BtRiQezg.js → components/BareModal.js} +1 -1
  63. package/dist/components/Breadcrumbs.js +83 -0
  64. package/dist/components/Button.js +83 -0
  65. package/dist/components/Callout.js +23 -0
  66. package/dist/components/Card.js +31 -0
  67. package/dist/components/CollapsiblePanel.js +77 -0
  68. package/dist/{chunks/ConfirmModal-aOR4O1QE.js → components/ConfirmModal.js} +4 -9
  69. package/dist/components/CopyToClipboard.js +81 -0
  70. package/dist/{chunks/Markdown-CM-FenNE.js → components/CreateModal.js} +9 -116
  71. package/dist/components/DescriptionList.js +42 -0
  72. package/dist/components/Dropdown.js +349 -0
  73. package/dist/components/EmptyState.js +27 -0
  74. package/dist/components/Filter.js +32 -0
  75. package/dist/components/FilterPill.js +13 -0
  76. package/dist/components/IconButton.js +34 -0
  77. package/dist/{chunks/Indicator-hBSIxOPK.js → components/Indicator.js} +1 -1
  78. package/dist/components/Input.js +88 -0
  79. package/dist/components/LetterBadge.js +13 -0
  80. package/dist/components/Listbox.js +123 -0
  81. package/dist/{chunks/Loader-BXoXTZGc.js → components/Loader.js} +1 -1
  82. package/dist/components/Markdown.js +15 -0
  83. package/dist/components/MultiSelect.js +171 -0
  84. package/dist/components/Overview.js +39 -0
  85. package/dist/components/PageHeader.js +194 -0
  86. package/dist/components/Pagination.js +35 -0
  87. package/dist/{chunks/Provider-CDYurraE.js → components/Provider.js} +1 -1
  88. package/dist/{chunks/RequiredMark-DfLdYbYZ.js → components/RequiredMark.js} +1 -1
  89. package/dist/components/SectionHeader.js +11 -0
  90. package/dist/components/SettingModeOption.js +30 -0
  91. package/dist/components/SettingRow.js +35 -0
  92. package/dist/components/SettingsCard.js +31 -0
  93. package/dist/components/SettingsGroup.js +17 -0
  94. package/dist/components/Sort.js +42 -0
  95. package/dist/components/StatusBadge.js +63 -0
  96. package/dist/components/SwitchToggle.js +59 -0
  97. package/dist/{chunks/SwitchToggleSmall-FcsaYSTs.js → components/SwitchToggleSmall.js} +1 -1
  98. package/dist/{chunks/Table-DU2MW8xz.js → components/Table.js} +3 -3
  99. package/dist/components/Toggle.js +20 -0
  100. package/dist/{chunks/Tooltip-K5HJr4_p.js → components/Tooltip.js} +2 -27
  101. package/dist/{chunks/StatusBadge-C1Blx_cW.js → components/dropdownUtils.js} +2 -63
  102. package/dist/{chunks/focus-D_iZJTW1.js → components/focus.js} +1 -1
  103. package/dist/components/ghostButton.js +7 -0
  104. package/dist/components/inputClasses.js +4 -0
  105. package/dist/components/keys.js +27 -0
  106. package/dist/components/relativeTime.js +32 -0
  107. package/dist/{chunks/useCssIsDark-DHr05dG2.js → components/useCssIsDark.js} +1 -1
  108. package/dist/{chunks/duration-BOv8Phl8.js → duration.js} +1 -1
  109. package/dist/editor/Editor.js +13 -0
  110. package/dist/editor/EditorField.js +53 -0
  111. package/dist/editor/FormCodePanel.js +173 -0
  112. package/dist/{chunks/Monaco-DJ8MW-Dq.js → editor/Monaco.js} +4 -2
  113. package/dist/editor/index.js +6 -1
  114. package/dist/editor/themes.js +91 -0
  115. package/dist/editor/workers.js +29 -0
  116. package/dist/editor/yaml.js +15 -0
  117. package/dist/file-explorer/FileExplorer.js +1402 -0
  118. package/dist/file-explorer/FileExplorerContext.js +370 -0
  119. package/dist/{chunks/CodePreviewEditor-YqQBz1YL.js → file-explorer/FilePreview/CodePreviewEditor.js} +3 -2
  120. package/dist/file-explorer/FilePreview/Inline.js +45 -0
  121. package/dist/file-explorer/FilePreview/StreamedBadge.js +16 -0
  122. package/dist/file-explorer/FilePreview/Viewer.js +526 -0
  123. package/dist/file-explorer/FilePreview/index.js +266 -0
  124. package/dist/file-explorer/FilePreview/parse.js +63 -0
  125. package/dist/file-explorer/FilePreview/previewCache.js +98 -0
  126. package/dist/file-explorer/FilePreview/previewType.js +151 -0
  127. package/dist/file-explorer/FilePreview/readCappedBytes.js +196 -0
  128. package/dist/file-explorer/FilePreview/useObjectBlobUrl.js +95 -0
  129. package/dist/file-explorer/FilePreview/useObjectText.js +109 -0
  130. package/dist/file-explorer/FilePreview/usePresignedUrl.js +73 -0
  131. package/dist/file-explorer/FileRow.js +165 -0
  132. package/dist/file-explorer/FileRowsWindow.js +92 -0
  133. package/dist/file-explorer/FileTable.js +172 -0
  134. package/dist/file-explorer/FileTableHeaders.js +49 -0
  135. package/dist/file-explorer/LoadMoreRow.js +46 -0
  136. package/dist/file-explorer/TreeView.js +376 -0
  137. package/dist/file-explorer/helpers.js +537 -0
  138. package/dist/file-explorer/index.js +7 -5671
  139. package/dist/file-explorer/lib/batch.js +39 -0
  140. package/dist/file-explorer/lib/errors.js +9 -0
  141. package/dist/file-explorer/lib/paging.js +124 -0
  142. package/dist/file-explorer/lib/utils.js +322 -0
  143. package/dist/file-explorer/toasts.js +400 -0
  144. package/dist/file-explorer/treeRows.js +73 -0
  145. package/dist/file-explorer/useNearEnd.js +27 -0
  146. package/dist/form/FieldWrapper.js +54 -0
  147. package/dist/form/Fields/BooleanField.js +51 -0
  148. package/dist/form/Fields/CheckboxGroupField.js +72 -0
  149. package/dist/form/Fields/ColorField.js +33 -0
  150. package/dist/form/Fields/DropdownField.js +49 -0
  151. package/dist/form/Fields/DurationField.js +130 -0
  152. package/dist/form/Fields/LabelField.js +19 -0
  153. package/dist/form/Fields/MultiDropdownField.js +40 -0
  154. package/dist/form/Fields/NumberField.js +51 -0
  155. package/dist/form/Fields/ObjectField.js +54 -0
  156. package/dist/form/Fields/RadioField.js +49 -0
  157. package/dist/form/Fields/RangeField.js +58 -0
  158. package/dist/form/Fields/ResourceOptionIcon.js +21 -0
  159. package/dist/form/Fields/StepField.js +6 -0
  160. package/dist/form/Fields/StringField.js +37 -0
  161. package/dist/form/Fields/TextAreaField.js +31 -0
  162. package/dist/form/Fields/durationValidity.js +11 -0
  163. package/dist/form/Form.js +643 -0
  164. package/dist/form/SpecialTypes/DropdownWrapper.js +30 -0
  165. package/dist/form/SpecialTypes/FormikCustomDropdown.js +122 -0
  166. package/dist/form/SpecialTypes/FormikCustomInput.js +111 -0
  167. package/dist/form/SpecialTypes/FormikMultiSelectDropdown.js +31 -0
  168. package/dist/form/SpecialTypes/FormikNumericInput.js +60 -0
  169. package/dist/form/Wizard/WizardContainer.js +138 -0
  170. package/dist/form/Wizard/WizardNavigation.js +92 -0
  171. package/dist/form/Wizard/WizardStepContent.js +35 -0
  172. package/dist/form/Wizard/WizardStepIndicator.js +108 -0
  173. package/dist/form/Wizard/useWizardState.js +118 -0
  174. package/dist/form/Wizard/utils.js +34 -0
  175. package/dist/form/fieldContext.js +26 -0
  176. package/dist/form/fieldRegistry.js +50 -0
  177. package/dist/form/index.js +17 -2321
  178. package/dist/{chunks/FieldWrapper-Cszwg-4B.js → form/lib.js} +2 -97
  179. package/dist/form/useParsedOpts.js +62 -0
  180. package/dist/form/usePrevious.js +11 -0
  181. package/dist/form/utils/checkShowIfObject.js +14 -0
  182. package/dist/form/utils/duration.js +69 -0
  183. package/dist/form/utils/getParentValue.js +23 -0
  184. package/dist/form/utils/getPlaceholder.js +9 -0
  185. package/dist/form/utils/getValueUsingPath.js +23 -0
  186. package/dist/form/utils/secondaryField.js +22 -0
  187. package/dist/graph/AnnotationBanner.js +141 -0
  188. package/dist/graph/Collapse.js +41 -0
  189. package/dist/graph/DependencyGraph.js +1398 -0
  190. package/dist/graph/JobSummary.js +104 -0
  191. package/dist/graph/MatrixGroup.js +107 -0
  192. package/dist/graph/Reveal.js +57 -0
  193. package/dist/graph/TreeView.js +711 -0
  194. package/dist/graph/index.js +1 -2519
  195. package/dist/graph/types.js +6 -0
  196. package/dist/index.js +46 -599
  197. package/dist/list/ActionToolbar.js +184 -0
  198. package/dist/list/HoverCard.js +73 -0
  199. package/dist/list/ListPage.js +145 -0
  200. package/dist/list/ListPager.js +59 -0
  201. package/dist/list/ListTable.js +163 -0
  202. package/dist/list/ListViewControls.js +372 -0
  203. package/dist/list/RowContextMenu.js +350 -0
  204. package/dist/list/UserHoverCard.js +117 -0
  205. package/dist/list/index.js +11 -2
  206. package/dist/list/listSearch.js +137 -0
  207. package/dist/list/listView.js +210 -0
  208. package/dist/list/textEntry.js +10 -0
  209. package/dist/{chunks/logviewer-BTKuQWzw.js → logviewer/LogViewer.js} +4 -82
  210. package/dist/logviewer/index.js +2 -1
  211. package/dist/logviewer/segments.js +80 -0
  212. package/package.json +1 -1
  213. package/dist/chunks/PageHeader-0kG_iypP.js +0 -692
  214. package/dist/chunks/SwitchToggle-DShNdcao.js +0 -758
  215. package/dist/chunks/editor-Dk1rbV75.js +0 -361
  216. package/dist/chunks/list-CJm875m7.js +0 -1418
  217. /package/dist/{chunks/MarkdownImpl-CyeTVvSt.js → components/MarkdownImpl.js} +0 -0
@@ -0,0 +1,88 @@
1
+ import { AlertIcon, EyeIcon, EyeOffIcon } from "../icons.js";
2
+ import { RequiredMark } from "./RequiredMark.js";
3
+ import cx from "classnames";
4
+ import { forwardRef, useId, useState } from "react";
5
+ import { jsx, jsxs } from "react/jsx-runtime";
6
+ //#region src/components/Input.tsx
7
+ var Input = forwardRef(({ label, error, className = "", mono, type, required, ...props }, ref) => {
8
+ const [showPassword, setShowPassword] = useState(false);
9
+ const isPassword = type === "password";
10
+ const inputType = isPassword && showPassword ? "text" : type;
11
+ const generatedId = useId();
12
+ const id = props.id ?? generatedId;
13
+ const errorId = `${id}-error`;
14
+ const describedBy = [props["aria-describedby"], error ? errorId : void 0].filter(Boolean).join(" ") || void 0;
15
+ const inputClasses = cx("w-full py-3 px-4 bg-[var(--theme-muted-panel-bg)] border border-[var(--theme-border)] rounded-lg text-[var(--theme-app)] text-sm transition-all duration-200 box-border", "focus:outline-none focus:border-[var(--theme-element)] focus:shadow-[0_0_0_3px_color-mix(in_srgb,var(--theme-element)_25%,transparent)]", "placeholder:text-[var(--theme-muted-text-color)]", "disabled:bg-[var(--theme-muted-panel-bg)] disabled:text-[var(--theme-muted-text-color)] disabled:cursor-not-allowed disabled:opacity-70", mono && "font-mono text-[0.8125rem]", error && "border-[#ef4444]", isPassword && "pr-11", className);
16
+ return /* @__PURE__ */ jsxs("div", {
17
+ className: "flex flex-col gap-1.5",
18
+ children: [
19
+ label && /* @__PURE__ */ jsxs("label", {
20
+ className: "text-[0.8125rem] font-medium text-[var(--theme-app)]",
21
+ htmlFor: id,
22
+ children: [label, required && /* @__PURE__ */ jsx(RequiredMark, {})]
23
+ }),
24
+ /* @__PURE__ */ jsxs("div", {
25
+ className: isPassword ? "relative w-full" : "",
26
+ children: [/* @__PURE__ */ jsx("input", {
27
+ ref,
28
+ type: inputType,
29
+ className: inputClasses,
30
+ ...props,
31
+ id,
32
+ required,
33
+ "aria-invalid": error ? true : props["aria-invalid"],
34
+ "aria-describedby": describedBy
35
+ }), isPassword && /* @__PURE__ */ jsx("button", {
36
+ type: "button",
37
+ className: "absolute right-3 top-1/2 -translate-y-1/2 bg-transparent border-none text-[var(--theme-muted-text-color)] cursor-pointer p-1 transition-colors duration-200 flex items-center justify-center hover:text-[var(--theme-app)]",
38
+ onClick: () => setShowPassword(!showPassword),
39
+ tabIndex: -1,
40
+ "aria-label": showPassword ? "Hide password" : "Show password",
41
+ children: showPassword ? /* @__PURE__ */ jsx(EyeOffIcon, { className: "w-5 h-5" }) : /* @__PURE__ */ jsx(EyeIcon, { className: "w-5 h-5" })
42
+ })]
43
+ }),
44
+ error && /* @__PURE__ */ jsxs("span", {
45
+ id: errorId,
46
+ role: "alert",
47
+ className: "text-[0.8125rem] text-[#ef4444] flex items-center gap-1.5",
48
+ children: [/* @__PURE__ */ jsx(AlertIcon, { className: "w-4 h-4" }), error]
49
+ })
50
+ ]
51
+ });
52
+ });
53
+ Input.displayName = "Input";
54
+ var Textarea = forwardRef(({ label, error, className = "", mono, required, ...props }, ref) => {
55
+ const generatedId = useId();
56
+ const id = props.id ?? generatedId;
57
+ const errorId = `${id}-error`;
58
+ const describedBy = [props["aria-describedby"], error ? errorId : void 0].filter(Boolean).join(" ") || void 0;
59
+ const textareaClasses = cx("w-full py-3 px-4 bg-[var(--theme-muted-panel-bg)] border border-[var(--theme-border)] rounded-lg text-[var(--theme-app)] text-sm transition-all duration-200 box-border min-h-[140px] resize-y", "focus:outline-none focus:border-[var(--theme-element)] focus:shadow-[0_0_0_3px_color-mix(in_srgb,var(--theme-element)_25%,transparent)]", "placeholder:text-[var(--theme-muted-text-color)]", mono && "font-mono text-[0.8125rem]", error && "border-[#ef4444]", className);
60
+ return /* @__PURE__ */ jsxs("div", {
61
+ className: "flex flex-col gap-1.5",
62
+ children: [
63
+ label && /* @__PURE__ */ jsxs("label", {
64
+ className: "text-[0.8125rem] font-medium text-[var(--theme-app)]",
65
+ htmlFor: id,
66
+ children: [label, required && /* @__PURE__ */ jsx(RequiredMark, {})]
67
+ }),
68
+ /* @__PURE__ */ jsx("textarea", {
69
+ ref,
70
+ className: textareaClasses,
71
+ ...props,
72
+ id,
73
+ required,
74
+ "aria-invalid": error ? true : props["aria-invalid"],
75
+ "aria-describedby": describedBy
76
+ }),
77
+ error && /* @__PURE__ */ jsxs("span", {
78
+ id: errorId,
79
+ role: "alert",
80
+ className: "text-[0.8125rem] text-[#ef4444] flex items-center gap-1.5",
81
+ children: [/* @__PURE__ */ jsx(AlertIcon, { className: "w-4 h-4" }), error]
82
+ })
83
+ ]
84
+ });
85
+ });
86
+ Textarea.displayName = "Textarea";
87
+ //#endregion
88
+ export { Input, Textarea };
@@ -0,0 +1,13 @@
1
+ import cx from "classnames";
2
+ import { jsx } from "react/jsx-runtime";
3
+ //#region src/components/LetterBadge.tsx
4
+ /** A compact letter badge ("AI", "PUB", "SSH") used as a type mark in place of
5
+ * an icon. Size the box and text via className (e.g. "h-5 w-5 text-[8px]"). */
6
+ function LetterBadge({ text, className }) {
7
+ return /* @__PURE__ */ jsx("span", {
8
+ className: cx("inline-flex shrink-0 items-center justify-center rounded-[3px] border theme-border font-bold leading-none tracking-tight text-(--theme-app)", className),
9
+ children: text
10
+ });
11
+ }
12
+ //#endregion
13
+ export { LetterBadge };
@@ -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 };