@parallelworks/ui 0.1.0 → 0.2.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 (102) hide show
  1. package/dist/assets/editor.worker-CuBRIwi-.js +14776 -0
  2. package/dist/assets/json.worker-8ytS02vz.js +22161 -0
  3. package/dist/assets/yaml.worker-DJC-VUcv.js +48367 -0
  4. package/dist/chunks/Indicator-fF8AVbjQ.js +158 -0
  5. package/dist/chunks/Loader-DQiZ75fa.js +25 -0
  6. package/dist/chunks/MarkdownImpl-Bq4QhrtA.js +33 -0
  7. package/dist/chunks/Monaco-CP_cL9gp.js +745 -0
  8. package/dist/chunks/Provider-C2VtPnh5.js +151 -0
  9. package/dist/chunks/SwitchToggleSmall-FcsaYSTs.js +14 -0
  10. package/dist/chunks/Table-DWuRINhu.js +855 -0
  11. package/dist/chunks/Tooltip-WgbiC_nd.js +71 -0
  12. package/dist/chunks/lib-DTgL8klR.js +191 -0
  13. package/dist/chunks/workers-Cjfjb8E7.js +119 -0
  14. package/dist/components/CollapsiblePanel.d.ts +27 -0
  15. package/dist/components/CopyToClipboard.d.ts +17 -0
  16. package/dist/components/Dropdown.d.ts +24 -0
  17. package/dist/components/Indicator.d.ts +4 -0
  18. package/dist/components/Listbox.d.ts +18 -0
  19. package/dist/components/Markdown.d.ts +7 -0
  20. package/dist/components/MarkdownImpl.d.ts +2 -0
  21. package/dist/components/MultiSelect.d.ts +19 -0
  22. package/dist/components/Overview.d.ts +12 -0
  23. package/dist/components/Provider.d.ts +145 -0
  24. package/dist/components/SectionHeader.d.ts +6 -0
  25. package/dist/components/SwitchToggle.d.ts +12 -0
  26. package/dist/components/SwitchToggleSmall.d.ts +6 -0
  27. package/dist/components/dropdownUtils.d.ts +18 -0
  28. package/dist/editor/Editor.d.ts +2 -0
  29. package/dist/editor/EditorField.d.ts +11 -0
  30. package/dist/editor/FormCodePanel.d.ts +8 -0
  31. package/dist/editor/Monaco.d.ts +31 -0
  32. package/dist/editor/index.d.ts +6 -0
  33. package/dist/editor/index.js +219 -0
  34. package/dist/editor/themes.d.ts +4 -0
  35. package/dist/editor/workers.d.ts +6 -0
  36. package/dist/form/FieldWrapper.d.ts +10 -0
  37. package/dist/form/Fields/BooleanField.d.ts +12 -0
  38. package/dist/form/Fields/BucketReadOnlyField.d.ts +7 -0
  39. package/dist/form/Fields/CheckboxGroupField.d.ts +18 -0
  40. package/dist/form/Fields/ColorField.d.ts +8 -0
  41. package/dist/form/Fields/DropdownField.d.ts +24 -0
  42. package/dist/form/Fields/DurationField.d.ts +13 -0
  43. package/dist/form/Fields/LabelField.d.ts +9 -0
  44. package/dist/form/Fields/MultiDropdownField.d.ts +18 -0
  45. package/dist/form/Fields/NumberField.d.ts +13 -0
  46. package/dist/form/Fields/ObjectField.d.ts +8 -0
  47. package/dist/form/Fields/RadioField.d.ts +9 -0
  48. package/dist/form/Fields/RangeField.d.ts +11 -0
  49. package/dist/form/Fields/ResourceOptionIcon.d.ts +11 -0
  50. package/dist/form/Fields/StepField.d.ts +3 -0
  51. package/dist/form/Fields/StringField.d.ts +17 -0
  52. package/dist/form/Fields/TextAreaField.d.ts +8 -0
  53. package/dist/form/Fields/durationValidity.d.ts +2 -0
  54. package/dist/form/Form.d.ts +105 -0
  55. package/dist/form/SpecialTypes/DropdownWrapper.d.ts +14 -0
  56. package/dist/form/SpecialTypes/FormikCustomDropdown.d.ts +53 -0
  57. package/dist/form/SpecialTypes/FormikCustomInput.d.ts +17 -0
  58. package/dist/form/SpecialTypes/FormikMultiSelectDropdown.d.ts +13 -0
  59. package/dist/form/SpecialTypes/FormikNumericInput.d.ts +9 -0
  60. package/dist/form/SpecialTypes/index.d.ts +3 -0
  61. package/dist/form/Wizard/WizardContainer.d.ts +5 -0
  62. package/dist/form/Wizard/WizardNavigation.d.ts +2 -0
  63. package/dist/form/Wizard/WizardStepContent.d.ts +8 -0
  64. package/dist/form/Wizard/WizardStepIndicator.d.ts +2 -0
  65. package/dist/form/Wizard/types.d.ts +171 -0
  66. package/dist/form/Wizard/useWizardState.d.ts +28 -0
  67. package/dist/form/Wizard/utils.d.ts +2 -0
  68. package/dist/form/fieldRegistry.d.ts +7 -0
  69. package/dist/form/index.d.ts +16 -0
  70. package/dist/form/index.js +2317 -0
  71. package/dist/form/lib.d.ts +15 -0
  72. package/dist/form/types/fieldComponentTypes.d.ts +32 -0
  73. package/dist/form/types/fieldTypes.d.ts +80 -0
  74. package/dist/form/types/workflow-schema.d.ts +1107 -0
  75. package/dist/form/useParsedOpts.d.ts +5 -0
  76. package/dist/form/usePrevious.d.ts +1 -0
  77. package/dist/form/utils/checkShowIfObject.d.ts +1 -0
  78. package/dist/form/utils/getParentValue.d.ts +1 -0
  79. package/dist/form/utils/getPlaceholder.d.ts +2 -0
  80. package/dist/form/utils/getValueUsingPath.d.ts +1 -0
  81. package/dist/form/utils/pwResolver.d.ts +18 -0
  82. package/dist/form/utils/secondaryField.d.ts +8 -0
  83. package/dist/form/utils/slurmDuration.d.ts +15 -0
  84. package/dist/icons.d.ts +1 -1
  85. package/dist/icons.js +2 -2
  86. package/dist/index.d.ts +17 -0
  87. package/dist/index.js +107 -323
  88. package/dist/logviewer/LogViewer.d.ts +18 -0
  89. package/dist/logviewer/index.d.ts +1 -0
  90. package/dist/logviewer/index.js +534 -0
  91. package/dist/logviewer/logviewer.css +70 -0
  92. package/dist/styles.css +1 -1
  93. package/dist/workflow/AnnotationBanner.d.ts +5 -0
  94. package/dist/workflow/Collapse.d.ts +6 -0
  95. package/dist/workflow/DependencyGraph.d.ts +15 -0
  96. package/dist/workflow/JobSummary.d.ts +38 -0
  97. package/dist/workflow/MatrixGroup.d.ts +41 -0
  98. package/dist/workflow/Reveal.d.ts +7 -0
  99. package/dist/workflow/TreeView.d.ts +42 -0
  100. package/dist/workflow/index.d.ts +1 -0
  101. package/dist/workflow/index.js +2330 -0
  102. package/package.json +60 -6
@@ -0,0 +1,855 @@
1
+ import { AngleDownIcon, AngleRightIcon, CaretDownIcon } from "../icons.js";
2
+ import { o as useStrings } from "./Provider-C2VtPnh5.js";
3
+ import { n as TOOLTIP_ID } from "./Tooltip-WgbiC_nd.js";
4
+ import { t as Loader } from "./Loader-DQiZ75fa.js";
5
+ import cx from "classnames";
6
+ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
7
+ import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
8
+ import { createPortal } from "react-dom";
9
+ import { Combobox, ComboboxButton, ComboboxInput, ComboboxOption, ComboboxOptions, Listbox, ListboxButton, ListboxOption, ListboxOptions, Switch, Transition } from "@headlessui/react";
10
+ import deepEqual from "fast-deep-equal";
11
+ import { usePopper } from "react-popper";
12
+ import AnimateHeight from "react-animate-height";
13
+ //#region src/components/dropdownUtils.tsx
14
+ function isCategory(option) {
15
+ return typeof option === "object" && option !== null && option !== void 0 && "options" in option;
16
+ }
17
+ function isOption(option) {
18
+ return typeof option === "object" && "label" in option && "value" in option && !("category" in option);
19
+ }
20
+ function normalizeOption(option) {
21
+ if (typeof option === "string") return {
22
+ label: option,
23
+ value: option
24
+ };
25
+ if (typeof option === "object" && option !== null && option !== void 0 && "options" in option) return {
26
+ category: option.category,
27
+ options: Array.isArray(option.options) ? option.options : []
28
+ };
29
+ return option;
30
+ }
31
+ function flattenOptions(options) {
32
+ const result = [];
33
+ for (const opt of options) {
34
+ const normalized = normalizeOption(opt);
35
+ if (isCategory(normalized)) {
36
+ const children = Array.isArray(normalized.options) ? normalized.options : [];
37
+ result.push(normalized);
38
+ result.push(...children);
39
+ } else result.push(normalized);
40
+ }
41
+ return result;
42
+ }
43
+ function filterOption(option, query) {
44
+ if (query === "") return true;
45
+ const q = String(query ?? "").toLowerCase().replace(/(-)/gm, "");
46
+ const label = String(option.label ?? "").toLowerCase().replace(/(-)/gm, "");
47
+ const secondary = option.secondaryValue !== void 0 ? String(option.secondaryValue).toLowerCase().replace(/(-)/gm, "") : "";
48
+ return label.includes(q) || secondary.includes(q);
49
+ }
50
+ function DropdownCaret() {
51
+ return /* @__PURE__ */ jsx(CaretDownIcon, { className: "text-neutral-400 absolute top-1/2 -translate-y-1/2 right-0 mr-3 inset-y-0 flex items-center rounded-r-md focus:outline-hidden" });
52
+ }
53
+ //#endregion
54
+ //#region src/components/Dropdown.tsx
55
+ var checkEquals = (val, opt) => {
56
+ if (typeof val === "object" && !Array.isArray(val)) return deepEqual(val, opt);
57
+ return val === opt;
58
+ };
59
+ function getOptionFromValue(value, options) {
60
+ if (value === void 0) return {
61
+ label: "",
62
+ value: ""
63
+ };
64
+ const found = options?.find((option) => {
65
+ if (typeof option === "string") return checkEquals(value, option);
66
+ else if (isCategory(option)) return option.options.find((opt) => checkEquals(value, opt.value));
67
+ else return checkEquals(value, option.value);
68
+ });
69
+ if (found) if (typeof found === "string") return {
70
+ label: found,
71
+ value: found
72
+ };
73
+ else if (isCategory(found)) return found.options.find((opt) => checkEquals(value, opt.value)) || {
74
+ label: JSON.stringify(value),
75
+ value
76
+ };
77
+ else return found;
78
+ const isResourceObject = value && typeof value === "object" && "name" in value && (value.$type === "computeResource" || value.type === "computeResource" || value.type === "bucket");
79
+ const fallbackLabel = typeof value === "string" ? value : isResourceObject ? value.name : JSON.stringify(value);
80
+ return {
81
+ label: fallbackLabel,
82
+ value: isResourceObject ? value : fallbackLabel
83
+ };
84
+ }
85
+ function Dropdown(props) {
86
+ const { onChange, value, options = [], ...others } = props;
87
+ const val = useMemo(() => {
88
+ return getOptionFromValue(value, options);
89
+ }, [value, options]);
90
+ const wrapperOnchange = (value) => {
91
+ if (onChange) onChange(value?.value);
92
+ };
93
+ return /* @__PURE__ */ jsx(DropdownHelper, {
94
+ value: val,
95
+ onChange: wrapperOnchange,
96
+ options: useMemo(() => {
97
+ if (!options || options.length === 0) return [];
98
+ return options.map((item) => {
99
+ if (isCategory(item)) return {
100
+ ...item,
101
+ options: item.options.map((opt) => {
102
+ if (typeof opt === "string") return {
103
+ label: opt,
104
+ value: opt
105
+ };
106
+ return opt;
107
+ })
108
+ };
109
+ else if (typeof item === "string") return {
110
+ label: item,
111
+ value: item
112
+ };
113
+ return item;
114
+ });
115
+ }, [options]),
116
+ ...others
117
+ });
118
+ }
119
+ function ActiveWatcher({ active, onChange }) {
120
+ const prev = useRef(null);
121
+ useEffect(() => {
122
+ if (prev.current !== active) {
123
+ onChange?.(active?.value);
124
+ prev.current = active;
125
+ }
126
+ }, [active, onChange]);
127
+ return null;
128
+ }
129
+ function DropdownHelper({ wrapperClassName = "w-full", className, textBoxClassName = "w-full", options = [], onChange, onActiveChange, value, id, ariaLabel, disabled = false, placeholder = "", loading = false, allowCustomValue = false, customValueLabel = "Use", portalEl }) {
130
+ const DEBOUNCE_MS = 500;
131
+ const [query, setQuery] = useState("");
132
+ const [referenceElement, setReferenceElement] = useState(null);
133
+ const [popperElement, setPopperElement] = useState(null);
134
+ const [boundaryEl, setBoundaryEl] = useState(null);
135
+ useEffect(() => {
136
+ if (!referenceElement) {
137
+ setBoundaryEl(null);
138
+ return;
139
+ }
140
+ const ref = referenceElement;
141
+ const dialog = ref.closest("[role=\"dialog\"]");
142
+ if (!dialog) {
143
+ setBoundaryEl(null);
144
+ return;
145
+ }
146
+ let node = ref.parentElement;
147
+ while (node) {
148
+ const style = getComputedStyle(node);
149
+ if (/(auto|scroll|hidden)/.test(`${style.overflowX} ${style.overflowY}`)) {
150
+ setBoundaryEl(node);
151
+ return;
152
+ }
153
+ if (node === dialog) break;
154
+ node = node.parentElement;
155
+ }
156
+ setBoundaryEl(dialog);
157
+ }, [referenceElement]);
158
+ const sameWidthModifier = useMemo(() => ({
159
+ name: "sameWidth",
160
+ enabled: true,
161
+ phase: "beforeWrite",
162
+ requires: ["computeStyles"],
163
+ fn: ({ state }) => {
164
+ state.styles.popper.width = `${state.rects.reference.width}px`;
165
+ },
166
+ effect: ({ state }) => {
167
+ state.elements.popper.style.width = `${state.elements.reference.offsetWidth}px`;
168
+ }
169
+ }), []);
170
+ const { styles, attributes } = usePopper(referenceElement, popperElement, {
171
+ strategy: "fixed",
172
+ modifiers: useMemo(() => boundaryEl ? [
173
+ sameWidthModifier,
174
+ {
175
+ name: "flip",
176
+ options: { boundary: boundaryEl }
177
+ },
178
+ {
179
+ name: "preventOverflow",
180
+ options: { boundary: boundaryEl }
181
+ }
182
+ ] : [sameWidthModifier], [boundaryEl, sameWidthModifier])
183
+ });
184
+ const debounceRef = useRef(null);
185
+ const buttonRef = useRef(null);
186
+ const flushCustomValue = useCallback((val) => {
187
+ onChange({
188
+ label: val,
189
+ value: val
190
+ });
191
+ }, [onChange]);
192
+ const onQueryChange = (val) => {
193
+ setQuery(val);
194
+ if (allowCustomValue) {
195
+ if (debounceRef.current) clearTimeout(debounceRef.current);
196
+ debounceRef.current = setTimeout(() => {
197
+ flushCustomValue(val);
198
+ debounceRef.current = null;
199
+ }, DEBOUNCE_MS);
200
+ }
201
+ };
202
+ const onInputBlur = () => {
203
+ if (allowCustomValue && debounceRef.current) {
204
+ clearTimeout(debounceRef.current);
205
+ debounceRef.current = null;
206
+ flushCustomValue(query);
207
+ }
208
+ setQuery("");
209
+ };
210
+ const onComboboxChange = (val) => {
211
+ if (debounceRef.current) {
212
+ clearTimeout(debounceRef.current);
213
+ debounceRef.current = null;
214
+ }
215
+ onChange(val);
216
+ };
217
+ const flattenedOptions = useMemo(() => {
218
+ const flatOptions = options.flatMap((option) => {
219
+ if (isCategory(option)) {
220
+ const filteredOptions = option.options.filter((opt) => filterOption(opt, query));
221
+ if (filteredOptions.length === 0) return [];
222
+ return [{
223
+ label: option.category || "",
224
+ value: option.category || "",
225
+ disabled: true,
226
+ category: true
227
+ }, ...filteredOptions];
228
+ }
229
+ if (filterOption(option, query)) return option;
230
+ return [];
231
+ });
232
+ if (allowCustomValue) {
233
+ const customValue = query || value?.value || "";
234
+ flatOptions.unshift({
235
+ label: `${customValueLabel} "${customValue}"`,
236
+ value: customValue
237
+ });
238
+ } else if (flatOptions.length === 0) return [{
239
+ label: "No options found",
240
+ value: "",
241
+ disabled: true
242
+ }];
243
+ return flatOptions;
244
+ }, [
245
+ options,
246
+ query,
247
+ value,
248
+ allowCustomValue,
249
+ customValueLabel
250
+ ]);
251
+ const comboOptions = /* @__PURE__ */ jsx(Fragment, { children: /* @__PURE__ */ jsx(ComboboxOptions, {
252
+ ref: setPopperElement,
253
+ style: styles.popper,
254
+ className: "bg-(--theme-input-bg) border-(--theme-border) text-(--theme-app) max-h-60! empty:invisible border overflow-auto rounded-md shadow-lg focus:outline-hidden sm:text-sm z-9999 data-[popper-reference-hidden=true]:invisible data-[popper-reference-hidden=true]:pointer-events-none",
255
+ ...attributes.popper,
256
+ children: ({ option }) => {
257
+ const optionLabel = typeof option === "string" ? option : option.label;
258
+ const optionDescription = typeof option !== "string" ? option.description : void 0;
259
+ const isCategoryRow = typeof option !== "string" && Boolean(option.category);
260
+ return /* @__PURE__ */ jsx(ComboboxOption, {
261
+ "data-testid": "combobox-option",
262
+ value: option,
263
+ className: cx("w-full group relative flex", optionDescription ? "min-h-10 py-2" : "h-10", isCategoryRow ? "text-[14px] font-bold pl-1 items-center" : "data-disabled:text-(--theme-muted-text-color) data-disabled:bg-(--theme-muted-panel-bg) data-disabled:cursor-not-allowed cursor-pointer items-center pr-9 pl-3 leading-5 data-focus:bg-(--theme-muted-panel-bg) data-focus:text-(--theme-app) data-focus:outline-hidden", "data-selected:border-l-2 data-selected:border-(--theme-link) data-selected:bg-(--theme-muted-panel-bg) data-selected:text-(--theme-app)"),
264
+ children: /* @__PURE__ */ jsxs("span", {
265
+ className: cx("flex gap-1.5", optionDescription ? "items-start min-w-0" : "items-center truncate"),
266
+ "data-tooltip-id": TOOLTIP_ID,
267
+ onMouseEnter: (e) => {
268
+ const inner = e.currentTarget.lastElementChild;
269
+ if (inner && inner.scrollWidth > inner.clientWidth) e.currentTarget.setAttribute("data-tooltip-content", optionLabel);
270
+ else e.currentTarget.removeAttribute("data-tooltip-content");
271
+ },
272
+ children: [typeof option !== "string" && option.icon, optionDescription ? /* @__PURE__ */ jsxs("span", {
273
+ className: "flex flex-col min-w-0",
274
+ children: [/* @__PURE__ */ jsx("span", {
275
+ className: "truncate",
276
+ children: optionLabel
277
+ }), /* @__PURE__ */ jsx("span", {
278
+ className: "text-(--theme-muted-text-color) text-xs leading-snug",
279
+ children: optionDescription
280
+ })]
281
+ }) : /* @__PURE__ */ jsx("span", {
282
+ className: "truncate",
283
+ children: optionLabel
284
+ })]
285
+ })
286
+ });
287
+ }
288
+ }) });
289
+ return /* @__PURE__ */ jsx("div", {
290
+ className: cx("relative rounded-md flex items-center", wrapperClassName),
291
+ children: /* @__PURE__ */ jsx(Combobox, {
292
+ "data-testid": "combobox",
293
+ className: cx("relative w-full", className),
294
+ as: "div",
295
+ by: checkEquals,
296
+ value,
297
+ onChange: onComboboxChange,
298
+ onClose: () => setQuery(""),
299
+ immediate: true,
300
+ virtual: {
301
+ options: flattenedOptions,
302
+ disabled: (option) => Boolean(option.disabled)
303
+ },
304
+ disabled,
305
+ children: ({ activeOption, open }) => /* @__PURE__ */ jsxs(Fragment, { children: [
306
+ onActiveChange && /* @__PURE__ */ jsx(ActiveWatcher, {
307
+ active: activeOption,
308
+ onChange: onActiveChange
309
+ }),
310
+ /* @__PURE__ */ jsx(ComboboxInput, {
311
+ id,
312
+ "aria-label": ariaLabel || void 0,
313
+ placeholder: loading ? "Loading..." : placeholder,
314
+ onBlur: onInputBlur,
315
+ ref: setReferenceElement,
316
+ onClick: () => {
317
+ if (!open) buttonRef.current?.click();
318
+ },
319
+ className: cx("placeholder:text-xs bg-(--theme-input-bg) border-(--theme-border) text-(--theme-app) focus:border-(--theme-element) focus:outline-none focus:ring-1 focus:ring-(--theme-element) w-full h-full text-ellipsis pr-8", "disabled:bg-(--theme-input-disabled-bg) disabled:text-(--theme-input-disabled-text) disabled:cursor-not-allowed", textBoxClassName),
320
+ autoComplete: "off",
321
+ onChange: (event) => onQueryChange(event.target.value),
322
+ displayValue: (opt) => {
323
+ return opt?.label?.replaceAll("\"", "") || query || "";
324
+ },
325
+ disabled
326
+ }),
327
+ /* @__PURE__ */ jsx(ComboboxButton, {
328
+ ref: buttonRef,
329
+ className: "absolute inset-y-0 right-0 flex items-center pr-3 disabled:cursor-not-allowed",
330
+ "data-testid": "combobox-button",
331
+ disabled,
332
+ children: /* @__PURE__ */ jsx(DropdownCaret, {})
333
+ }),
334
+ typeof document !== "undefined" && createPortal(comboOptions, portalEl ?? document.querySelector(".ds-root") ?? document.body)
335
+ ] })
336
+ })
337
+ });
338
+ }
339
+ //#endregion
340
+ //#region src/components/Listbox.tsx
341
+ function CustomListbox({ options = [], handleOptionSelected, type, allowSearch = false, closeOnSelect = true, className = "", invalid = false }) {
342
+ const { dropdown: strings } = useStrings();
343
+ const [filter, setFilter] = useState("");
344
+ const [controlledOpen, setControlledOpen] = useState(false);
345
+ const optionsToShow = options.filter((option) => !option.selected && option.label && option.label.toLowerCase().includes(filter.toLowerCase()));
346
+ function useOutsideAlerter(ref) {
347
+ useEffect(() => {
348
+ function handleClickOutside(event) {
349
+ if (ref.current && event.target instanceof Node && !ref.current.contains(event.target)) {
350
+ setControlledOpen(false);
351
+ setFilter("");
352
+ }
353
+ }
354
+ document.addEventListener("mousedown", handleClickOutside);
355
+ return () => {
356
+ document.removeEventListener("mousedown", handleClickOutside);
357
+ };
358
+ }, [ref]);
359
+ }
360
+ const wrapperRef = useRef(null);
361
+ useOutsideAlerter(wrapperRef);
362
+ const optionsElement = /* @__PURE__ */ jsxs(ListboxOptions, {
363
+ static: true,
364
+ className: "absolute w-full py-1 z-50 theme-input rounded-md",
365
+ children: [allowSearch && /* @__PURE__ */ jsx("div", {
366
+ className: "pl-2 pr-4 mb-1",
367
+ children: /* @__PURE__ */ jsx("input", {
368
+ autoComplete: "off",
369
+ type: "search",
370
+ autoFocus: true,
371
+ onChange: (e) => setFilter(e.target.value),
372
+ value: filter,
373
+ className: "w-full p-1 theme-input",
374
+ onKeyDown: (e) => {
375
+ if (![
376
+ "ArrowUp",
377
+ "ArrowDown",
378
+ "Enter",
379
+ "Home",
380
+ "End",
381
+ "Escape"
382
+ ].includes(e.key)) e.stopPropagation();
383
+ }
384
+ })
385
+ }), /* @__PURE__ */ jsx("div", {
386
+ className: "overflow-auto max-h-60 theme-panel",
387
+ children: optionsToShow.length > 0 ? optionsToShow.map((option, index) => /* @__PURE__ */ jsx(ListboxOption, {
388
+ className: "relative hover:theme-hover select-none pl-2 pr-4",
389
+ value: option.value,
390
+ children: /* @__PURE__ */ jsx("div", {
391
+ className: "w-full flex flex-row",
392
+ children: /* @__PURE__ */ jsxs("div", {
393
+ className: "w-3/4 py-2 flex items-center",
394
+ children: [
395
+ /* @__PURE__ */ jsx("div", {
396
+ className: "w-4 h-6 btn btn-info text-xl line-height-0 mr-2",
397
+ children: "+"
398
+ }),
399
+ option.icon && /* @__PURE__ */ jsx("span", {
400
+ className: "mr-2 flex items-center",
401
+ children: option.icon
402
+ }),
403
+ /* @__PURE__ */ jsx("span", {
404
+ className: "mr-2",
405
+ children: option.label
406
+ }),
407
+ /* @__PURE__ */ jsx("span", {
408
+ className: "italic",
409
+ children: option.secondaryLabel
410
+ })
411
+ ]
412
+ })
413
+ }, index)
414
+ }, index)) : /* @__PURE__ */ jsx("div", {
415
+ className: "w-full flex flex-row",
416
+ children: /* @__PURE__ */ jsx("div", {
417
+ className: "w-3/4 py-2 pl-2 capitalize flex items-center",
418
+ children: filter === "" ? `All ${type} Added` : `No ${type} Found`
419
+ })
420
+ })
421
+ })]
422
+ });
423
+ return /* @__PURE__ */ jsxs(Listbox, {
424
+ as: "div",
425
+ className: cx("relative mt-1 theme-input border theme-border rounded-md", className),
426
+ ref: wrapperRef,
427
+ onChange: handleOptionSelected,
428
+ children: [/* @__PURE__ */ jsxs(ListboxButton, {
429
+ onClick: () => setControlledOpen((prev) => !prev),
430
+ className: cx("relative w-full py-2 pl-3 text-left", invalid && "border-red-600 focus:border-red-600 focus:ring-red-500"),
431
+ children: [/* @__PURE__ */ jsx("span", {
432
+ className: "block truncate",
433
+ children: strings.select(type)
434
+ }), /* @__PURE__ */ jsx("span", {
435
+ className: "pointer-events-none absolute inset-y-0 right-0 flex items-center justify-items-center",
436
+ children: /* @__PURE__ */ jsx(AngleDownIcon, {
437
+ className: "h-5 w-8",
438
+ "aria-hidden": "true"
439
+ })
440
+ })]
441
+ }), closeOnSelect ? /* @__PURE__ */ jsx(Transition, {
442
+ leave: "transition ease-in duration-100",
443
+ leaveFrom: "opacity-100",
444
+ leaveTo: "opacity-0",
445
+ children: optionsElement || null
446
+ }) : /* @__PURE__ */ jsx(Fragment, { children: controlledOpen && optionsElement })]
447
+ });
448
+ }
449
+ //#endregion
450
+ //#region src/components/MultiSelect.tsx
451
+ function MultiSelectDropdown({ options, value, onChange, id, className, wrapperClassName = "w-full", textBoxClassName, disabled = false, placeholder, loading = false, searchable = true, maxTagCount = 2, compareBy }) {
452
+ const strings = useStrings();
453
+ const [query, setQuery] = useState("");
454
+ const [referenceEl, setReferenceEl] = useState(null);
455
+ const [popperEl, setPopperEl] = useState(null);
456
+ const { styles, attributes } = usePopper(referenceEl, popperEl, {
457
+ placement: "bottom-start",
458
+ modifiers: [{
459
+ name: "offset",
460
+ options: { offset: [0, 4] }
461
+ }]
462
+ });
463
+ const allOptions = useMemo(() => flattenOptions(options), [options]);
464
+ const compare = compareBy ?? ((a, b) => a === b);
465
+ const selectedOptions = useMemo(() => {
466
+ const result = [];
467
+ for (const val of value) {
468
+ const found = allOptions.find((opt) => isOption(opt) && compare(opt.value, val));
469
+ if (found) result.push(found);
470
+ }
471
+ return result;
472
+ }, [
473
+ value,
474
+ allOptions,
475
+ compare
476
+ ]);
477
+ const filteredOptions = useMemo(() => {
478
+ if (!searchable || query.trim() === "") return allOptions;
479
+ const result = [];
480
+ for (const opt of allOptions) if (isCategory(opt)) {
481
+ const matchedChildren = (Array.isArray(opt.options) ? opt.options : []).filter((o) => filterOption(o, query));
482
+ if (matchedChildren.length > 0) result.push(opt, ...matchedChildren);
483
+ } else if (isOption(opt) && filterOption(opt, query)) result.push(opt);
484
+ return result;
485
+ }, [
486
+ allOptions,
487
+ query,
488
+ searchable
489
+ ]);
490
+ const display = useMemo(() => {
491
+ const shown = selectedOptions.slice(0, maxTagCount);
492
+ return {
493
+ label: shown.map((o) => o.label).join(", "),
494
+ overflow: selectedOptions.length - shown.length
495
+ };
496
+ }, [selectedOptions, maxTagCount]);
497
+ const handleChange = useCallback((newValues) => {
498
+ if (!Array.isArray(newValues)) return;
499
+ onChange(newValues);
500
+ }, [onChange]);
501
+ const isDisabled = disabled || loading;
502
+ const isEmpty = filteredOptions.length === 0;
503
+ return /* @__PURE__ */ jsx(Combobox, {
504
+ multiple: true,
505
+ value: Array.isArray(value) ? value : [],
506
+ onChange: handleChange,
507
+ disabled: isDisabled,
508
+ onClose: () => setQuery(""),
509
+ by: compare,
510
+ children: ({ open }) => /* @__PURE__ */ jsxs("div", {
511
+ ref: setReferenceEl,
512
+ className: cx("relative", wrapperClassName),
513
+ children: [
514
+ /* @__PURE__ */ jsx(ComboboxButton, {
515
+ as: "div",
516
+ id,
517
+ 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),
518
+ children: loading ? /* @__PURE__ */ jsx("span", {
519
+ className: "theme-muted-text",
520
+ children: strings.loading
521
+ }) : selectedOptions.length > 0 ? /* @__PURE__ */ jsxs(Fragment, { children: [/* @__PURE__ */ jsx("span", {
522
+ className: "min-w-0 truncate",
523
+ children: display.label
524
+ }), display.overflow > 0 && /* @__PURE__ */ jsxs("span", {
525
+ className: "ml-1 shrink-0 theme-muted-text",
526
+ children: ["+", display.overflow]
527
+ })] }) : /* @__PURE__ */ jsx("span", {
528
+ className: "theme-muted-text truncate",
529
+ children: placeholder
530
+ })
531
+ }),
532
+ /* @__PURE__ */ jsx(DropdownCaret, {}),
533
+ open && /* @__PURE__ */ jsxs(ComboboxOptions, {
534
+ ref: setPopperEl,
535
+ static: true,
536
+ "data-testid": "msd-list",
537
+ style: styles.popper,
538
+ ...attributes.popper,
539
+ className: "theme-panel z-10 max-h-60 w-full overflow-auto rounded-md shadow-lg focus:outline-none",
540
+ children: [searchable && /* @__PURE__ */ jsx("div", {
541
+ className: "sticky top-0 theme-panel p-2 border-b z-10",
542
+ children: /* @__PURE__ */ jsx("input", {
543
+ placeholder,
544
+ "data-1p-ignore": true,
545
+ autoComplete: "off",
546
+ type: "text",
547
+ className: "theme-input w-full",
548
+ value: query,
549
+ onChange: (e) => setQuery(e.target.value),
550
+ onKeyDown: (e) => e.stopPropagation(),
551
+ autoFocus: true
552
+ })
553
+ }), /* @__PURE__ */ jsx("div", {
554
+ className: "py-1",
555
+ children: isEmpty ? /* @__PURE__ */ jsx("div", {
556
+ className: "px-4 py-2 text-sm theme-muted-text",
557
+ children: strings.dropdown.noOptionsFound
558
+ }) : filteredOptions.map((opt, index) => {
559
+ if (isCategory(opt)) return /* @__PURE__ */ jsx("li", {
560
+ role: "presentation",
561
+ className: "px-4 py-2 text-sm font-bold theme-muted-text",
562
+ children: opt.category
563
+ }, `category-${opt.category ?? "uncat"}-${index}`);
564
+ const option = opt;
565
+ return /* @__PURE__ */ jsx(ComboboxOption, {
566
+ value: option.value,
567
+ disabled: option.disabled,
568
+ "data-testid": `msd-option-${String(option.value)}`,
569
+ 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"),
570
+ children: ({ selected }) => /* @__PURE__ */ jsxs("div", {
571
+ className: "flex items-center",
572
+ children: [
573
+ /* @__PURE__ */ jsx("span", {
574
+ className: "absolute inset-y-0 left-0 flex items-center pl-3",
575
+ children: /* @__PURE__ */ jsx("input", {
576
+ autoComplete: "off",
577
+ type: "checkbox",
578
+ checked: selected,
579
+ readOnly: true,
580
+ className: "h-4 w-4 cursor-pointer",
581
+ "aria-hidden": "true"
582
+ })
583
+ }),
584
+ option.icon && /* @__PURE__ */ jsx("span", {
585
+ className: "mr-2 flex items-center",
586
+ children: option.icon
587
+ }),
588
+ /* @__PURE__ */ jsx("div", {
589
+ className: "flex flex-col",
590
+ children: /* @__PURE__ */ jsx("span", {
591
+ className: "block truncate",
592
+ children: option.label
593
+ })
594
+ })
595
+ ]
596
+ })
597
+ }, `option-${String(option.value)}`);
598
+ })
599
+ })]
600
+ })
601
+ ]
602
+ })
603
+ });
604
+ }
605
+ //#endregion
606
+ //#region src/components/CollapsiblePanel.tsx
607
+ var noop = () => {};
608
+ function ControlledCollapsiblePanel({ title = "", children, open, setOpen, onClick = noop, wrapperElement, customizedButton = null, className }) {
609
+ const toggleOpen = useCallback(() => {
610
+ if (onClick) onClick();
611
+ setOpen?.((open) => !open);
612
+ }, [setOpen, onClick]);
613
+ const Wrapper = wrapperElement ? wrapperElement : React.Fragment;
614
+ return React.isValidElement(title) ? /* @__PURE__ */ jsxs(Fragment, { children: [title, /* @__PURE__ */ jsx(Wrapper, { children: /* @__PURE__ */ jsx(AnimateHeight, {
615
+ duration: 300,
616
+ height: open ? "auto" : 0,
617
+ children
618
+ }) })] }) : /* @__PURE__ */ jsxs("div", {
619
+ className: cx("border border-solid rounded-2xl border-(--theme-border) bg-(--theme-panel-bg) text-(--theme-panel) mb-1 w-full", className),
620
+ children: [/* @__PURE__ */ jsxs("div", {
621
+ className: cx(!open && "text-(--theme-muted-text-color)", "w-full flex items-center justify-between transform ease-in transition text-sm py-3 px-2 cursor-pointer"),
622
+ onClick: toggleOpen,
623
+ children: [/* @__PURE__ */ jsxs("div", {
624
+ className: "flex items-center w-full",
625
+ children: [/* @__PURE__ */ jsx(AngleRightIcon, { className: cx(open && "transform rotate-90", "px-1 ml-1 text-[1.25rem] transition ease-in") }), /* @__PURE__ */ jsx("span", {
626
+ className: "px-2 font-bold select-none",
627
+ children: title?.toString()
628
+ })]
629
+ }), /* @__PURE__ */ jsx("div", {
630
+ onClick: (e) => {
631
+ e.stopPropagation();
632
+ },
633
+ children: customizedButton
634
+ })]
635
+ }), /* @__PURE__ */ jsx(AnimateHeight, {
636
+ duration: 300,
637
+ height: open ? "auto" : 0,
638
+ children
639
+ })]
640
+ });
641
+ }
642
+ function UncontrolledCollapsiblePanel({ title, children, onClick, wrapperElement, initialState = true, className, customizedButton = null }) {
643
+ const [open, setOpen] = React.useState(initialState);
644
+ return /* @__PURE__ */ jsx(ControlledCollapsiblePanel, {
645
+ title: typeof title === "function" ? title(open, setOpen) : title,
646
+ open,
647
+ setOpen,
648
+ onClick,
649
+ wrapperElement,
650
+ className,
651
+ customizedButton,
652
+ children
653
+ });
654
+ }
655
+ function MaybeCollapsible({ className, initialState, children, title, customizedButton, collapsible }) {
656
+ if (collapsible) return /* @__PURE__ */ jsx(UncontrolledCollapsiblePanel, {
657
+ className,
658
+ initialState,
659
+ title,
660
+ customizedButton,
661
+ children
662
+ });
663
+ return /* @__PURE__ */ jsx("div", {
664
+ className,
665
+ children
666
+ });
667
+ }
668
+ //#endregion
669
+ //#region src/components/SectionHeader.tsx
670
+ function SectionHeader({ children, className = "" }) {
671
+ return /* @__PURE__ */ jsx("div", {
672
+ className: cx("w-full text-lg font-semibold", className),
673
+ children
674
+ });
675
+ }
676
+ //#endregion
677
+ //#region src/components/StatusBadge.tsx
678
+ var variantStyles = {
679
+ default: "bg-(--theme-muted-panel-bg) text-(--theme-app) border-(--theme-border)",
680
+ success: "bg-emerald-500/10 text-emerald-500 border-emerald-500/20",
681
+ warning: "bg-amber-500/10 text-amber-500 border-amber-500/20",
682
+ error: "bg-red-500/10 text-red-500 border-red-500/20",
683
+ info: "bg-blue-500/10 text-blue-500 border-blue-500/20",
684
+ muted: "bg-(--theme-muted-panel-bg)/50 text-(--theme-muted-text-color) border-(--theme-border)"
685
+ };
686
+ var pulseColors = {
687
+ default: "bg-(--theme-app)",
688
+ success: "bg-emerald-500",
689
+ warning: "bg-amber-500",
690
+ error: "bg-red-500",
691
+ info: "bg-blue-500",
692
+ muted: "bg-(--theme-muted-text-color)"
693
+ };
694
+ function StatusBadge({ children, variant = "default", pulse = false, size = "sm", className }) {
695
+ return /* @__PURE__ */ jsxs("span", {
696
+ className: cx("inline-flex items-center gap-1.5 rounded-full border font-medium", size === "sm" && "px-2 py-0.5 text-[10px]", size === "md" && "px-2.5 py-1 text-xs", variantStyles[variant], className),
697
+ children: [pulse && /* @__PURE__ */ jsxs("span", {
698
+ className: "relative flex h-2 w-2",
699
+ children: [/* @__PURE__ */ jsx("span", { className: cx("absolute inline-flex h-full w-full animate-ping rounded-full opacity-75", pulseColors[variant]) }), /* @__PURE__ */ jsx("span", { className: cx("relative inline-flex h-2 w-2 rounded-full", pulseColors[variant]) })]
700
+ }), children]
701
+ });
702
+ }
703
+ function StatusDot({ variant = "default", pulse = false, size = 8, className }) {
704
+ return /* @__PURE__ */ jsxs("span", {
705
+ className: cx("relative inline-flex", className),
706
+ style: {
707
+ width: size,
708
+ height: size
709
+ },
710
+ children: [pulse && /* @__PURE__ */ jsx("span", { className: cx("absolute inline-flex h-full w-full animate-ping rounded-full opacity-75", pulseColors[variant]) }), /* @__PURE__ */ jsx("span", {
711
+ className: cx("relative inline-flex rounded-full", pulseColors[variant]),
712
+ style: {
713
+ width: size,
714
+ height: size
715
+ }
716
+ })]
717
+ });
718
+ }
719
+ //#endregion
720
+ //#region src/components/SwitchToggle.tsx
721
+ function SwitchToggle({ onChange, value = void 0, yesLabel = "Yes", noLabel = "No", disabled = false, datatip = "", invalid = false }) {
722
+ const [enabled, setEnabled] = useState(value ?? false);
723
+ const [isFocused, setIsFocused] = useState(false);
724
+ const setIsEnabled = (e) => {
725
+ setEnabled(e);
726
+ onChange(e);
727
+ };
728
+ useEffect(() => {
729
+ if (value !== void 0) setEnabled(value);
730
+ }, [value]);
731
+ const checked = value ?? enabled;
732
+ return /* @__PURE__ */ jsx("div", {
733
+ "data-tooltip-content": datatip || void 0,
734
+ "data-tooltip-id": datatip ? TOOLTIP_ID : void 0,
735
+ className: cx("w-[198px] h-[30px] overflow-hidden shadow-sm rounded-md cursor-pointer ring-(--theme-border) ring-1", invalid && "border-red-600 focus:border-red-600 focus:ring-red-500 ring-1 ring-red-500", !invalid && isFocused && "ring-1 ring-[rgba(82,168,236,.8)] drop-shadow-[0_1px_2px_rgba(82,168,236,0.8)]"),
736
+ children: /* @__PURE__ */ jsx(Switch, {
737
+ checked,
738
+ onChange: setIsEnabled,
739
+ className: "text-white text-sm shadow-sm rounded-md cursor-pointer",
740
+ onClick: (e) => e.stopPropagation(),
741
+ onFocus: () => setIsFocused(true),
742
+ onBlur: () => setIsFocused(false),
743
+ children: /* @__PURE__ */ jsxs("div", {
744
+ className: cx(checked ? "translate-x-0" : "-translate-x-[100px]", "relative transform flex flex-row ease-in-out duration-500", disabled && "cursor-not-allowed opacity-50"),
745
+ children: [
746
+ /* @__PURE__ */ jsx("div", {
747
+ className: "inline text-center capitalize px-2 py-1 w-[99px] border-0",
748
+ style: {
749
+ background: `linear-gradient(
750
+ to bottom,
751
+ var(--theme-element, #04c) 0%,
752
+ var(--theme-element, #08c) 100%
753
+ )`,
754
+ color: "var(--theme-element-text, #ffffff)"
755
+ },
756
+ children: yesLabel
757
+ }),
758
+ /* @__PURE__ */ jsx("div", { className: "inline px-2 py-1 h-8 w-[99px] bg-linear-to-b from-white to-[#e6e6e6]" }),
759
+ /* @__PURE__ */ jsx("div", {
760
+ className: "inline text-center capitalize px-2 py-1 w-[99px] bg-linear-to-b from-[#e6e6e6] to-white bg-[#04c] text-black",
761
+ children: noLabel
762
+ })
763
+ ]
764
+ })
765
+ })
766
+ });
767
+ }
768
+ //#endregion
769
+ //#region src/components/Table.tsx
770
+ function Item({ wrap = false, children, className, colspan = 1, ...tdProps }) {
771
+ const yPadding = className?.includes("py-") ? "" : "py-4";
772
+ const xPadding = className?.includes("px-") ? "" : "px-2";
773
+ return /* @__PURE__ */ jsx("td", {
774
+ ...tdProps,
775
+ colSpan: colspan,
776
+ className: cx(yPadding, xPadding, wrap ? "" : "whitespace-nowrap", className),
777
+ children
778
+ });
779
+ }
780
+ function CompactItem({ wrap = false, children, className, colspan = 1, ...tdProps }) {
781
+ return /* @__PURE__ */ jsx("td", {
782
+ ...tdProps,
783
+ colSpan: colspan,
784
+ className: cx("px-2 text-sm font-medium", !wrap && "whitespace-nowrap", className),
785
+ children
786
+ });
787
+ }
788
+ function Header({ children, className, style, colspan = 1, onClick, caps = true }) {
789
+ return /* @__PURE__ */ jsx("th", {
790
+ scope: "col",
791
+ colSpan: colspan,
792
+ style,
793
+ className: cx(className, className?.includes("py-") ? "" : "py-3", className?.includes("px-") ? "" : "px-3", className?.includes("text-") ? "" : "text-left", "text-xs font-medium", caps ? "uppercase tracking-wider" : "", onClick && "cursor-pointer hover:opacity-80 transition-opacity"),
794
+ onClick,
795
+ children
796
+ });
797
+ }
798
+ var isHeaderChild = (child) => {
799
+ if (!React.isValidElement(child)) return false;
800
+ return child.type === Header || typeof child.type === "function" && child.type.isTableHeader === true;
801
+ };
802
+ var getHeaders = (children) => children.filter(isHeaderChild);
803
+ function Table({ borderless = false, panel = true, className = "", wrapperClassName = "", tbodyClassName = "divide-y", theadClassName = "theme-muted-panel", children, roundedTop = false, rounded = false, roundedBottom = false, isLoading = false, tableProps }) {
804
+ const ChildrenArr = React.Children.toArray(children);
805
+ const Headers = getHeaders(ChildrenArr);
806
+ return /* @__PURE__ */ jsx("div", {
807
+ className: cx("flex flex-col w-full", !wrapperClassName.split(" ").some((cls) => cls.startsWith("overflow-")) && "overflow-hidden", wrapperClassName),
808
+ children: isLoading ? /* @__PURE__ */ jsx("div", {
809
+ className: "flex justify-center items-center h-32",
810
+ children: /* @__PURE__ */ jsx(Loader, {})
811
+ }) : /* @__PURE__ */ jsx("div", {
812
+ className: cx("align-middle inline-block min-w-full overflow-x-auto", panel && "theme-panel", !borderless && "border theme-border", rounded && "rounded-2xl", roundedBottom && "rounded-b-2xl", roundedTop && "rounded-t-2xl"),
813
+ children: /* @__PURE__ */ jsxs("table", {
814
+ className: cx(className, "min-w-full divide-y theme-border"),
815
+ ...tableProps,
816
+ children: [/* @__PURE__ */ jsx("thead", {
817
+ className: theadClassName,
818
+ children: /* @__PURE__ */ jsx("tr", { children: Headers })
819
+ }), /* @__PURE__ */ jsx("tbody", {
820
+ className: tbodyClassName,
821
+ children: ChildrenArr.filter((c) => !isHeaderChild(c))
822
+ })]
823
+ })
824
+ })
825
+ });
826
+ }
827
+ function CompactTable({ wrapperClassName = "", className = "", tbodyClassName = "divide-y", children, roundedTop = false, rounded = false, roundedBottom = false }) {
828
+ const ChildrenArr = React.Children.toArray(children);
829
+ const Headers = getHeaders(ChildrenArr);
830
+ return /* @__PURE__ */ jsx("div", {
831
+ className: cx("flex flex-col w-full", !wrapperClassName.split(" ").some((cls) => cls.startsWith("overflow-")) && "overflow-hidden", wrapperClassName),
832
+ children: /* @__PURE__ */ jsx("div", {
833
+ className: cx("theme-panel inline-block min-w-full align-middle overflow-x-auto", rounded && "rounded-2xl", roundedBottom && "rounded-b-2xl pb-1", roundedTop && "rounded-t-2xl"),
834
+ children: /* @__PURE__ */ jsxs("table", {
835
+ className: cx("min-w-full divide-y theme-border", className),
836
+ children: [/* @__PURE__ */ jsx("thead", {
837
+ className: "theme-muted-panel",
838
+ children: /* @__PURE__ */ jsx("tr", {
839
+ className: "divide-x",
840
+ children: Headers
841
+ })
842
+ }), /* @__PURE__ */ jsx("tbody", {
843
+ className: tbodyClassName,
844
+ children: ChildrenArr.filter((c) => !isHeaderChild(c))
845
+ })]
846
+ })
847
+ })
848
+ });
849
+ }
850
+ Table.Header = Header;
851
+ Table.Item = Item;
852
+ CompactTable.Header = Header;
853
+ CompactTable.Item = CompactItem;
854
+ //#endregion
855
+ export { isOption as _, StatusDot as a, MaybeCollapsible as c, CustomListbox as d, Dropdown as f, isCategory as g, flattenOptions as h, StatusBadge as i, UncontrolledCollapsiblePanel as l, filterOption as m, Table as n, SectionHeader as o, DropdownCaret as p, SwitchToggle as r, ControlledCollapsiblePanel as s, CompactTable as t, MultiSelectDropdown as u };