@simplybusiness/mobius 9.3.0 → 9.3.2

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 (86) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/dist/cjs/components/AddressLookup/AddressLookup.js.map +2 -2
  3. package/dist/cjs/components/AddressLookup/index.js.map +2 -2
  4. package/dist/cjs/components/Checkbox/Checkbox.js.map +2 -2
  5. package/dist/cjs/components/Checkbox/CheckboxGroup.js.map +2 -2
  6. package/dist/cjs/components/Checkbox/index.js.map +2 -2
  7. package/dist/cjs/components/Combobox/Combobox.js.map +2 -2
  8. package/dist/cjs/components/Combobox/index.js.map +2 -2
  9. package/dist/cjs/components/DateField/DateField.js.map +2 -2
  10. package/dist/cjs/components/DateField/index.js.map +2 -2
  11. package/dist/cjs/components/ErrorMessage/ErrorMessage.js.map +2 -2
  12. package/dist/cjs/components/ErrorMessage/index.js.map +2 -2
  13. package/dist/cjs/components/ExpandableText/ExpandableText.js.map +2 -2
  14. package/dist/cjs/components/ExpandableText/index.js.map +2 -2
  15. package/dist/cjs/components/MaskedField/MaskedField.js.map +2 -2
  16. package/dist/cjs/components/MaskedField/index.js.map +2 -2
  17. package/dist/cjs/components/NumberField/NumberField.js.map +2 -2
  18. package/dist/cjs/components/NumberField/index.js.map +2 -2
  19. package/dist/cjs/components/PasswordField/PasswordField.js.map +2 -2
  20. package/dist/cjs/components/PasswordField/ShowHideButton.js.map +2 -2
  21. package/dist/cjs/components/PasswordField/index.js.map +2 -2
  22. package/dist/cjs/components/Popover/Popover.js +21 -1
  23. package/dist/cjs/components/Popover/Popover.js.map +2 -2
  24. package/dist/cjs/components/Popover/index.js +21 -1
  25. package/dist/cjs/components/Popover/index.js.map +2 -2
  26. package/dist/cjs/components/Radio/Radio.js.map +2 -2
  27. package/dist/cjs/components/Radio/RadioGroup.js.map +2 -2
  28. package/dist/cjs/components/Radio/index.js.map +2 -2
  29. package/dist/cjs/components/Select/Select.js.map +2 -2
  30. package/dist/cjs/components/Select/index.js.map +2 -2
  31. package/dist/cjs/components/TextArea/TextArea.js.map +2 -2
  32. package/dist/cjs/components/TextArea/index.js.map +2 -2
  33. package/dist/cjs/components/TextField/TextField.js.map +2 -2
  34. package/dist/cjs/components/TextField/index.js.map +2 -2
  35. package/dist/cjs/components/index.js +21 -1
  36. package/dist/cjs/components/index.js.map +2 -2
  37. package/dist/cjs/index.js +21 -1
  38. package/dist/cjs/index.js.map +2 -2
  39. package/dist/cjs/meta.json +42 -42
  40. package/dist/esm/{chunk-ASLEVOVU.js → chunk-MXQ4PJF4.js} +1 -1
  41. package/dist/esm/{chunk-IS74FB4O.js → chunk-O5YEU5TG.js} +23 -3
  42. package/dist/esm/chunk-O5YEU5TG.js.map +7 -0
  43. package/dist/esm/components/AddressLookup/AddressLookup.js +2 -2
  44. package/dist/esm/components/AddressLookup/index.js +2 -2
  45. package/dist/esm/components/Checkbox/Checkbox.js +2 -2
  46. package/dist/esm/components/Checkbox/CheckboxGroup.js +2 -2
  47. package/dist/esm/components/Checkbox/index.js +2 -2
  48. package/dist/esm/components/Combobox/Combobox.js +2 -2
  49. package/dist/esm/components/Combobox/index.js +2 -2
  50. package/dist/esm/components/DateField/DateField.js +2 -2
  51. package/dist/esm/components/DateField/index.js +2 -2
  52. package/dist/esm/components/ErrorMessage/ErrorMessage.js +2 -2
  53. package/dist/esm/components/ErrorMessage/index.js +2 -2
  54. package/dist/esm/components/ExpandableText/ExpandableText.js +2 -2
  55. package/dist/esm/components/ExpandableText/index.js +2 -2
  56. package/dist/esm/components/MaskedField/MaskedField.js +2 -2
  57. package/dist/esm/components/MaskedField/index.js +2 -2
  58. package/dist/esm/components/NumberField/NumberField.js +2 -2
  59. package/dist/esm/components/NumberField/index.js +2 -2
  60. package/dist/esm/components/PasswordField/PasswordField.js +2 -2
  61. package/dist/esm/components/PasswordField/ShowHideButton.js +2 -2
  62. package/dist/esm/components/PasswordField/index.js +2 -2
  63. package/dist/esm/components/Popover/Popover.js +1 -1
  64. package/dist/esm/components/Popover/index.js +1 -1
  65. package/dist/esm/components/Radio/Radio.js +2 -2
  66. package/dist/esm/components/Radio/RadioGroup.js +2 -2
  67. package/dist/esm/components/Radio/index.js +2 -2
  68. package/dist/esm/components/Select/Select.js +2 -2
  69. package/dist/esm/components/Select/index.js +2 -2
  70. package/dist/esm/components/TextArea/TextArea.js +2 -2
  71. package/dist/esm/components/TextArea/index.js +2 -2
  72. package/dist/esm/components/TextField/TextField.js +2 -2
  73. package/dist/esm/components/TextField/index.js +2 -2
  74. package/dist/esm/components/index.js +2 -2
  75. package/dist/esm/index.js +2 -2
  76. package/dist/esm/meta.json +72 -72
  77. package/dist/tsconfig.build.tsbuildinfo +1 -1
  78. package/package.json +3 -1
  79. package/src/components/Combobox/Combobox.mdx +50 -6
  80. package/src/components/ErrorMessage/ErrorMessage.css +4 -4
  81. package/src/components/Modal/Modal.css +1 -1
  82. package/src/components/Popover/Popover.css +2 -2
  83. package/src/components/Popover/Popover.test.tsx +94 -0
  84. package/src/components/Popover/Popover.tsx +30 -2
  85. package/dist/esm/chunk-IS74FB4O.js.map +0 -7
  86. /package/dist/esm/{chunk-ASLEVOVU.js.map → chunk-MXQ4PJF4.js.map} +0 -0
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@simplybusiness/mobius",
3
3
  "license": "UNLICENSED",
4
- "version": "9.3.0",
4
+ "version": "9.3.2",
5
5
  "description": "Core library of Mobius react components",
6
6
  "repository": {
7
7
  "type": "git",
@@ -23,6 +23,7 @@
23
23
  "import": "./dist/esm/index.js",
24
24
  "default": "./dist/esm/index.js"
25
25
  },
26
+ "./package.json": "./package.json",
26
27
  "./src/*.css": "./src/*.css"
27
28
  },
28
29
  "publishConfig": {
@@ -36,6 +37,7 @@
36
37
  "import": "./dist/esm/index.js",
37
38
  "default": "./dist/esm/index.js"
38
39
  },
40
+ "./package.json": "./package.json",
39
41
  "./src/*.css": "./src/*.css"
40
42
  }
41
43
  },
@@ -35,15 +35,58 @@ type ComboboxOptions = T[] | ComboboxOptionGroup<T>[];
35
35
 
36
36
  ### Dynamic / asynchronous use
37
37
 
38
- `Combobox` provides a useful primitive with which to build more dynamic selector components, such as `Trade Selector` and `Adddress Lookup`.
38
+ `Combobox` provides a useful primitive with which to build more dynamic selector components, such as `Trade Selector` and `Address Lookup`.
39
39
 
40
- For these kinds of component, options (list) data is not known and must be fetched, typically from an API, as the user types. In this case, the `options` prop can be overloaded with a function that returns a promise.
40
+ For these kinds of component, options (list) data is not known and must be fetched, typically from an API, as the user types. Use the `asyncOptions` prop with a function that receives the current input and returns a promise of options:
41
41
 
42
42
  ```ts
43
- type OptionsFetcher = (inputValue: string) => Promise<Options>;
43
+ type AsyncOptionsFetcher = (
44
+ inputValue: string,
45
+ options?: { signal?: AbortSignal },
46
+ ) => Promise<Options>;
44
47
  ```
45
48
 
46
- In asynchronous mode, you are strongly encouraged to provide a `delay` value in milliseconds, to debounce API requests.
49
+ The Combobox calls `asyncOptions` **imperatively** when the debounced input changes. Pass the optional `signal` to your fetch so in-flight requests can be cancelled when the user types again.
50
+
51
+ - Provide a `delay` value (e.g. 300ms) to debounce API requests.
52
+ - Use `minSearchLength` to avoid fetching until the user has typed enough characters.
53
+
54
+ **When options come from parent state** (e.g. TanStack Query's `data` from `useQuery`, or a separate fetch triggered by `onChange`), use the sync `options` prop instead of `asyncOptions`. The Combobox only re-calls `asyncOptions` when the debounced input changes, so it won't see updates when your parent state changes. Pass `options={...}` derived from your state so the options update when the fetch completes.
55
+
56
+ **When using TanStack Query** (or similar) with `asyncOptions`, avoid calling Hooks (like `useQuery`) inside `asyncOptions`, as this violates the [Rules of Hooks](https://react.dev/reference/rules/rules-of-hooks). Instead, use `queryClient.fetchQuery` inside `asyncOptions`, or call `useQuery` at the component level and pass `options={data ?? []}` to the Combobox:
57
+
58
+ - ❌ **Bad**: `useQuery` inside `asyncOptions` — `useQuery` is a React Hook and must be called at the top level of a component, not from an imperative callback. While `useQuery` *can* re-run when the query key includes the input, it should not be invoked from `asyncOptions`.
59
+ - ✅ **Good**: `queryClient.fetchQuery` inside `asyncOptions` — imperative, query key includes input, respects AbortSignal.
60
+
61
+ Example with TanStack Query:
62
+
63
+ {/* prettier-ignore */}
64
+ ```jsx
65
+ import { useQueryClient } from "@tanstack/react-query";
66
+ import { Combobox } from "@simplybusiness/mobius";
67
+
68
+ function FruitSelector() {
69
+ const queryClient = useQueryClient();
70
+ const fetchOptions = async (
71
+ inputValue: string,
72
+ { signal }: { signal?: AbortSignal } = {}
73
+ ) => {
74
+ return queryClient.fetchQuery({
75
+ queryKey: ["fruits", inputValue],
76
+ queryFn: () => fetchFruits(inputValue, { signal }),
77
+ });
78
+ };
79
+ return (
80
+ <Combobox
81
+ label="Select a fruit"
82
+ asyncOptions={fetchOptions}
83
+ delay={300}
84
+ minSearchLength={3}
85
+ />
86
+ );
87
+ }
88
+ // fetchFruits(inputValue, { signal }) is your API function — pass signal for cancellation
89
+ ```
47
90
 
48
91
  ### Overriding selection behaviour
49
92
 
@@ -138,6 +181,7 @@ import { search } from "@simplybusiness/icons";
138
181
  You can customize how options are rendered using the `optionComponent` prop. This allows you to create custom layouts, add icons, or apply custom styling to individual options.
139
182
 
140
183
  The `optionComponent` prop accepts a component that receives two props:
184
+
141
185
  - `option`: The option data object
142
186
  - `isHighlighted`: A boolean indicating if the option is currently highlighted
143
187
 
@@ -147,7 +191,7 @@ The `optionComponent` prop accepts a component that receives two props:
147
191
  const options = [
148
192
  { id: "apple", label: "Apple", title: "Heading 1" },
149
193
  { id: "apricot", label: "Apricot", title: "Heading 2" },
150
- { id: "etc", label: "etc.", title: "Heading 3" }
194
+ { id: "etc", label: "etc.", title: "Heading 3" },
151
195
  ];
152
196
 
153
197
  function MyCustomOptionComponent({ option, isHighlighted }) {
@@ -159,7 +203,7 @@ function MyCustomOptionComponent({ option, isHighlighted }) {
159
203
  );
160
204
  }
161
205
 
162
- <Combobox options={OPTIONS} optionComponent={MyCustomOptionComponent} />
206
+ <Combobox options={OPTIONS} optionComponent={MyCustomOptionComponent} />;
163
207
  ```
164
208
 
165
209
  <Story of={ComboboxStories.CustomOptionComponent} />
@@ -4,7 +4,7 @@
4
4
  gap: var(--error-message-grid-gap, var(--size-xs));
5
5
  grid-template-columns: min-content 1fr;
6
6
  color: var(--color-error);
7
-
7
+
8
8
  & a {
9
9
  color: var(--color-link);
10
10
  outline: none;
@@ -24,9 +24,9 @@
24
24
  }
25
25
  }
26
26
 
27
- .mobius-error-message__icon {
28
- width: var(--error-message-icon-width, auto);
29
- height: var(--error-message-icon-height, auto);
27
+ .mobius-error-message__icon.mobius-icon {
28
+ width: var(--error-message-icon-width, 1em);
29
+ height: var(--error-message-icon-height, 1em);
30
30
  overflow: hidden;
31
31
  }
32
32
 
@@ -138,7 +138,7 @@
138
138
  }
139
139
  }
140
140
 
141
- .mobius-modal__close {
141
+ .mobius-modal__close.mobius-button {
142
142
  /* negative padding to match the padding of the header, so it aligns
143
143
  horizontally */
144
144
  padding: calc(var(--size-sm) * -1);
@@ -19,7 +19,7 @@
19
19
  padding-bottom: var(--size-sm);
20
20
  }
21
21
 
22
- .mobius-popover__close-button {
22
+ .mobius-popover__close-button.mobius-button {
23
23
  padding: 0;
24
24
  border: none;
25
25
  margin-left: auto;
@@ -27,7 +27,7 @@
27
27
  color: var(--color-text-popover);
28
28
  }
29
29
 
30
- .mobius-popover__close-icon {
30
+ .mobius-popover__close-icon.mobius-icon {
31
31
  height: 1.1em;
32
32
  }
33
33
 
@@ -127,6 +127,100 @@ describe("Popover", () => {
127
127
  });
128
128
  });
129
129
 
130
+ describe("click isolation", () => {
131
+ it("does not activate a parent label when clicking popover content", async () => {
132
+ const triggerText = "Click me";
133
+ const bodyText = "Popover body";
134
+ const onCheckboxChange = vi.fn();
135
+
136
+ render(
137
+ <label htmlFor="test-checkbox">
138
+ <input
139
+ id="test-checkbox"
140
+ type="checkbox"
141
+ onChange={onCheckboxChange}
142
+ />
143
+ <Popover trigger={<button type="button">{triggerText}</button>}>
144
+ <span>{bodyText}</span>
145
+ </Popover>
146
+ </label>,
147
+ );
148
+
149
+ fireEvent.click(screen.getByText(triggerText));
150
+
151
+ await waitFor(() => {
152
+ expect(screen.getByText(bodyText)).toBeInTheDocument();
153
+ });
154
+
155
+ fireEvent.click(screen.getByText(bodyText));
156
+
157
+ expect(onCheckboxChange).not.toHaveBeenCalled();
158
+ });
159
+
160
+ it("allows default behavior for links inside the popover", async () => {
161
+ const triggerText = "Click me";
162
+ const onCheckboxChange = vi.fn();
163
+
164
+ render(
165
+ <label htmlFor="test-checkbox">
166
+ <input
167
+ id="test-checkbox"
168
+ type="checkbox"
169
+ onChange={onCheckboxChange}
170
+ />
171
+ <Popover trigger={<button type="button">{triggerText}</button>}>
172
+ <a href="https://example.com">Example link</a>
173
+ </Popover>
174
+ </label>,
175
+ );
176
+
177
+ fireEvent.click(screen.getByText(triggerText));
178
+
179
+ await waitFor(() => {
180
+ expect(screen.getByText("Example link")).toBeInTheDocument();
181
+ });
182
+
183
+ const link = screen.getByText("Example link");
184
+
185
+ const clickEvent = new MouseEvent("click", { bubbles: true });
186
+ const preventDefaultSpy = vi.spyOn(clickEvent, "preventDefault");
187
+
188
+ link.dispatchEvent(clickEvent);
189
+
190
+ expect(preventDefaultSpy).not.toHaveBeenCalled();
191
+ expect(onCheckboxChange).not.toHaveBeenCalled();
192
+ });
193
+
194
+ it("does not activate a parent label when clicking the close button", async () => {
195
+ const triggerText = "Click me";
196
+ const bodyText = "Popover body";
197
+ const onCheckboxChange = vi.fn();
198
+
199
+ render(
200
+ <label htmlFor="test-checkbox">
201
+ <input
202
+ id="test-checkbox"
203
+ type="checkbox"
204
+ onChange={onCheckboxChange}
205
+ />
206
+ <Popover trigger={<button type="button">{triggerText}</button>}>
207
+ <span>{bodyText}</span>
208
+ </Popover>
209
+ </label>,
210
+ );
211
+
212
+ fireEvent.click(screen.getByText(triggerText));
213
+
214
+ await waitFor(() => {
215
+ expect(screen.getByText(bodyText)).toBeInTheDocument();
216
+ });
217
+
218
+ fireEvent.click(screen.getByLabelText("Close"));
219
+
220
+ expect(onCheckboxChange).not.toHaveBeenCalled();
221
+ });
222
+ });
223
+
130
224
  describe("events", () => {
131
225
  it("calls onOpen when Popover is opened", async () => {
132
226
  const sampleText = "Sample Text";
@@ -12,7 +12,7 @@ import {
12
12
  import { cross } from "@simplybusiness/icons";
13
13
  import classNames from "classnames/dedupe";
14
14
  import type { ReactElement, ReactNode, RefAttributes } from "react";
15
- import { cloneElement, useRef, useState } from "react";
15
+ import { cloneElement, useCallback, useEffect, useRef, useState } from "react";
16
16
  import { useWindowEvent } from "@simplybusiness/mobius-hooks";
17
17
  import type { DOMProps } from "../../types";
18
18
  import { Button } from "../Button";
@@ -38,6 +38,7 @@ const OFFSET_FROM_CONTENT_DEFAULT = 10;
38
38
  export const Popover = (props: PopoverProps) => {
39
39
  const { trigger, children, onOpen, onClose, className } = props;
40
40
  const arrowRef = useRef(null);
41
+ const floatingContainerRef = useRef<HTMLDivElement | null>(null);
41
42
  const [isOpen, setIsOpen] = useState(false);
42
43
  const { refs, floatingStyles, context } = useFloating({
43
44
  open: isOpen,
@@ -72,6 +73,33 @@ export const Popover = (props: PopoverProps) => {
72
73
  className,
73
74
  );
74
75
 
76
+ const setFloatingRef = useCallback(
77
+ (node: HTMLDivElement | null) => {
78
+ refs.setFloating(node);
79
+ floatingContainerRef.current = node;
80
+ },
81
+ [refs],
82
+ );
83
+
84
+ // Native listener to prevent clicks inside the popover from activating
85
+ // interactive ancestors. Must be native because React's onClick fires
86
+ // too late via delegation.
87
+ useEffect(() => {
88
+ const el = floatingContainerRef.current;
89
+ if (!el) return;
90
+
91
+ const preventLabelActivation = (e: Event) => {
92
+ const target = e.target as HTMLElement;
93
+ // Allow default behavior for interactive elements (links, inputs, etc.)
94
+ // so they remain functional inside the popover.
95
+ if (!target.closest("a[href], input, select, textarea")) {
96
+ e.preventDefault();
97
+ }
98
+ };
99
+ el.addEventListener("click", preventLabelActivation);
100
+ return () => el.removeEventListener("click", preventLabelActivation);
101
+ }, [isOpen]);
102
+
75
103
  const toggleVisibility = () => {
76
104
  if (isOpen) {
77
105
  setIsOpen(false);
@@ -107,7 +135,7 @@ export const Popover = (props: PopoverProps) => {
107
135
  {isOpen && (
108
136
  <div
109
137
  className={containerClasses}
110
- ref={refs.setFloating}
138
+ ref={setFloatingRef}
111
139
  style={floatingStyles}
112
140
  {...getFloatingProps()}
113
141
  >
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../src/components/Popover/Popover.tsx"],
4
- "sourcesContent": ["import {\n FloatingArrow,\n arrow,\n autoUpdate,\n flip,\n offset,\n shift,\n useDismiss,\n useFloating,\n useInteractions,\n} from \"@floating-ui/react\";\nimport { cross } from \"@simplybusiness/icons\";\nimport classNames from \"classnames/dedupe\";\nimport type { ReactElement, ReactNode, RefAttributes } from \"react\";\nimport { cloneElement, useRef, useState } from \"react\";\nimport { useWindowEvent } from \"@simplybusiness/mobius-hooks\";\nimport type { DOMProps } from \"../../types\";\nimport { Button } from \"../Button\";\nimport { Icon } from \"../Icon\";\nimport \"./Popover.css\";\n\nexport type PopoverElementType = HTMLDivElement;\n\nexport interface PopoverProps\n extends DOMProps, RefAttributes<PopoverElementType> {\n children?: ReactNode;\n trigger: ReactElement;\n /** Callback that fires each time the accordion is opened */\n onOpen?: () => void;\n /** Callback that fires each time the accordion is closed */\n onClose?: () => void;\n /** Custom class name for setting specific CSS */\n className?: string;\n}\n\nconst OFFSET_FROM_CONTENT_DEFAULT = 10;\n\nexport const Popover = (props: PopoverProps) => {\n const { trigger, children, onOpen, onClose, className } = props;\n const arrowRef = useRef(null);\n const [isOpen, setIsOpen] = useState(false);\n const { refs, floatingStyles, context } = useFloating({\n open: isOpen,\n onOpenChange: setIsOpen,\n whileElementsMounted: autoUpdate,\n middleware: [\n arrow({\n element: arrowRef,\n }),\n offset(OFFSET_FROM_CONTENT_DEFAULT),\n shift(),\n flip(),\n ],\n });\n const dismiss = useDismiss(context, {\n bubbles: true,\n outsidePress: (event: MouseEvent) => {\n // Prevent 'onClose' from firing when clicking the toggle to close\n const toggle = refs.reference.current as HTMLElement;\n const isToggleClick = !toggle?.contains(event.target as HTMLElement);\n if (isToggleClick) {\n onClose?.();\n }\n return true;\n },\n });\n const { getReferenceProps, getFloatingProps } = useInteractions([dismiss]);\n\n const containerClasses = classNames(\n \"mobius\",\n \"mobius-popover__container\",\n className,\n );\n\n const toggleVisibility = () => {\n if (isOpen) {\n setIsOpen(false);\n onClose?.();\n return;\n }\n\n setIsOpen(true);\n onOpen?.();\n };\n\n const triggerComponent = cloneElement(trigger, {\n ref: refs.setReference,\n className: classNames(\n (trigger.props as { className?: string }).className,\n \"mobius-popover__toggle\",\n ),\n onClick: toggleVisibility,\n ...getReferenceProps(),\n } as Record<string, unknown>);\n\n useWindowEvent(\"keydown\", e => {\n if (e.key === \"Escape\") {\n onClose?.();\n e.preventDefault();\n e.stopPropagation();\n }\n });\n\n return (\n <>\n {triggerComponent}\n {isOpen && (\n <div\n className={containerClasses}\n ref={refs.setFloating}\n style={floatingStyles}\n {...getFloatingProps()}\n >\n <div className=\"mobius-popover\">\n <header className=\"mobius-popover__header\">\n <Button\n type=\"button\"\n className=\"mobius-popover__close-button\"\n onClick={toggleVisibility}\n aria-label=\"Close\"\n variant=\"ghost\"\n >\n <Icon\n icon={cross}\n size=\"md\"\n className=\"mobius-popover__close-icon\"\n />\n </Button>\n </header>\n <div className=\"mobius-popover__body\">{children}</div>\n </div>\n <FloatingArrow\n ref={arrowRef}\n context={context}\n width={20}\n className=\"mobius-popover__arrow-icon\"\n />\n </div>\n )}\n </>\n );\n};\n"],
5
- "mappings": ";;;;;;;;AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,aAAa;AACtB,OAAO,gBAAgB;AAEvB,SAAS,cAAc,QAAQ,gBAAgB;AAC/C,SAAS,sBAAsB;AAI/B,OAAO;AAqFH,mBAkBY,KATN,YATN;AArEJ,IAAM,8BAA8B;AAE7B,IAAM,UAAU,CAAC,UAAwB;AAC9C,QAAM,EAAE,SAAS,UAAU,QAAQ,SAAS,UAAU,IAAI;AAC1D,QAAM,WAAW,OAAO,IAAI;AAC5B,QAAM,CAAC,QAAQ,SAAS,IAAI,SAAS,KAAK;AAC1C,QAAM,EAAE,MAAM,gBAAgB,QAAQ,IAAI,YAAY;AAAA,IACpD,MAAM;AAAA,IACN,cAAc;AAAA,IACd,sBAAsB;AAAA,IACtB,YAAY;AAAA,MACV,MAAM;AAAA,QACJ,SAAS;AAAA,MACX,CAAC;AAAA,MACD,OAAO,2BAA2B;AAAA,MAClC,MAAM;AAAA,MACN,KAAK;AAAA,IACP;AAAA,EACF,CAAC;AACD,QAAM,UAAU,WAAW,SAAS;AAAA,IAClC,SAAS;AAAA,IACT,cAAc,CAAC,UAAsB;AAEnC,YAAM,SAAS,KAAK,UAAU;AAC9B,YAAM,gBAAgB,CAAC,QAAQ,SAAS,MAAM,MAAqB;AACnE,UAAI,eAAe;AACjB,kBAAU;AAAA,MACZ;AACA,aAAO;AAAA,IACT;AAAA,EACF,CAAC;AACD,QAAM,EAAE,mBAAmB,iBAAiB,IAAI,gBAAgB,CAAC,OAAO,CAAC;AAEzE,QAAM,mBAAmB;AAAA,IACvB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAEA,QAAM,mBAAmB,MAAM;AAC7B,QAAI,QAAQ;AACV,gBAAU,KAAK;AACf,gBAAU;AACV;AAAA,IACF;AAEA,cAAU,IAAI;AACd,aAAS;AAAA,EACX;AAEA,QAAM,mBAAmB,aAAa,SAAS;AAAA,IAC7C,KAAK,KAAK;AAAA,IACV,WAAW;AAAA,MACR,QAAQ,MAAiC;AAAA,MAC1C;AAAA,IACF;AAAA,IACA,SAAS;AAAA,IACT,GAAG,kBAAkB;AAAA,EACvB,CAA4B;AAE5B,iBAAe,WAAW,OAAK;AAC7B,QAAI,EAAE,QAAQ,UAAU;AACtB,gBAAU;AACV,QAAE,eAAe;AACjB,QAAE,gBAAgB;AAAA,IACpB;AAAA,EACF,CAAC;AAED,SACE,iCACG;AAAA;AAAA,IACA,UACC;AAAA,MAAC;AAAA;AAAA,QACC,WAAW;AAAA,QACX,KAAK,KAAK;AAAA,QACV,OAAO;AAAA,QACN,GAAG,iBAAiB;AAAA,QAErB;AAAA,+BAAC,SAAI,WAAU,kBACb;AAAA,gCAAC,YAAO,WAAU,0BAChB;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,WAAU;AAAA,gBACV,SAAS;AAAA,gBACT,cAAW;AAAA,gBACX,SAAQ;AAAA,gBAER;AAAA,kBAAC;AAAA;AAAA,oBACC,MAAM;AAAA,oBACN,MAAK;AAAA,oBACL,WAAU;AAAA;AAAA,gBACZ;AAAA;AAAA,YACF,GACF;AAAA,YACA,oBAAC,SAAI,WAAU,wBAAwB,UAAS;AAAA,aAClD;AAAA,UACA;AAAA,YAAC;AAAA;AAAA,cACC,KAAK;AAAA,cACL;AAAA,cACA,OAAO;AAAA,cACP,WAAU;AAAA;AAAA,UACZ;AAAA;AAAA;AAAA,IACF;AAAA,KAEJ;AAEJ;",
6
- "names": []
7
- }