@open-mercato/ui 0.5.1-develop.2953.6647bb2c43 → 0.5.1-develop.2964.d5ac4a6ebb
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.
- package/.turbo/turbo-build.log +1 -1
- package/AGENTS.md +8 -0
- package/dist/backend/CrudForm.js +57 -29
- package/dist/backend/CrudForm.js.map +2 -2
- package/dist/backend/DataTable.js +32 -14
- package/dist/backend/DataTable.js.map +2 -2
- package/dist/backend/FilterOverlay.js +23 -17
- package/dist/backend/FilterOverlay.js.map +2 -2
- package/dist/backend/JsonBuilder.js +32 -18
- package/dist/backend/JsonBuilder.js.map +2 -2
- package/dist/backend/columns/ColumnChooserPanel.js +12 -13
- package/dist/backend/columns/ColumnChooserPanel.js.map +2 -2
- package/dist/backend/custom-fields/FieldDefinitionsEditor.js +71 -62
- package/dist/backend/custom-fields/FieldDefinitionsEditor.js.map +2 -2
- package/dist/backend/date-range/DateRangeSelect.js +11 -10
- package/dist/backend/date-range/DateRangeSelect.js.map +2 -2
- package/dist/backend/date-range/InlineDateRangeSelect.js +10 -22
- package/dist/backend/date-range/InlineDateRangeSelect.js.map +2 -2
- package/dist/backend/detail/ActivitiesSection.js +20 -12
- package/dist/backend/detail/ActivitiesSection.js.map +2 -2
- package/dist/backend/detail/AddressEditor.js +24 -7
- package/dist/backend/detail/AddressEditor.js.map +2 -2
- package/dist/backend/detail/InlineEditors.js +12 -6
- package/dist/backend/detail/InlineEditors.js.map +2 -2
- package/dist/backend/detail/NotesSection.js +20 -14
- package/dist/backend/detail/NotesSection.js.map +2 -2
- package/dist/backend/filters/AdvancedFilterBuilder.js +52 -24
- package/dist/backend/filters/AdvancedFilterBuilder.js.map +2 -2
- package/dist/backend/injection/InjectedField.js +12 -7
- package/dist/backend/injection/InjectedField.js.map +2 -2
- package/dist/backend/inputs/ComboboxInput.js.map +2 -2
- package/dist/backend/inputs/EventSelect.js +22 -6
- package/dist/backend/inputs/EventSelect.js.map +2 -2
- package/dist/backend/inputs/PhoneNumberField.js +2 -2
- package/dist/backend/inputs/PhoneNumberField.js.map +2 -2
- package/dist/backend/inputs/TimeInput.js +9 -10
- package/dist/backend/inputs/TimeInput.js.map +2 -2
- package/dist/backend/messages/message-compose-form-groups.js +12 -7
- package/dist/backend/messages/message-compose-form-groups.js.map +2 -2
- package/dist/backend/messages/useMessageCompose.js +7 -1
- package/dist/backend/messages/useMessageCompose.js.map +2 -2
- package/dist/frontend/LanguageSwitcher.js +19 -14
- package/dist/frontend/LanguageSwitcher.js.map +2 -2
- package/dist/index.js +5 -0
- package/dist/index.js.map +2 -2
- package/dist/primitives/checkbox-field.js +17 -5
- package/dist/primitives/checkbox-field.js.map +2 -2
- package/dist/primitives/input.js +71 -14
- package/dist/primitives/input.js.map +2 -2
- package/dist/primitives/radio-field.js +74 -0
- package/dist/primitives/radio-field.js.map +7 -0
- package/dist/primitives/radio.js +37 -0
- package/dist/primitives/radio.js.map +7 -0
- package/dist/primitives/select.js +155 -0
- package/dist/primitives/select.js.map +7 -0
- package/dist/primitives/switch-field.js +76 -0
- package/dist/primitives/switch-field.js.map +7 -0
- package/dist/primitives/switch.js +17 -3
- package/dist/primitives/switch.js.map +2 -2
- package/dist/primitives/textarea.js +48 -12
- package/dist/primitives/textarea.js.map +2 -2
- package/dist/primitives/tooltip.js +44 -15
- package/dist/primitives/tooltip.js.map +2 -2
- package/package.json +5 -3
- package/src/backend/CrudForm.tsx +104 -37
- package/src/backend/DataTable.tsx +38 -20
- package/src/backend/FilterOverlay.tsx +35 -21
- package/src/backend/JsonBuilder.tsx +38 -20
- package/src/backend/__tests__/FieldDefinitionsEditor.test.tsx +23 -6
- package/src/backend/columns/ColumnChooserPanel.tsx +9 -10
- package/src/backend/custom-fields/FieldDefinitionsEditor.tsx +120 -87
- package/src/backend/date-range/DateRangeSelect.tsx +19 -12
- package/src/backend/date-range/InlineDateRangeSelect.tsx +16 -20
- package/src/backend/detail/ActivitiesSection.tsx +35 -23
- package/src/backend/detail/AddressEditor.tsx +30 -16
- package/src/backend/detail/InlineEditors.tsx +21 -11
- package/src/backend/detail/NotesSection.tsx +35 -25
- package/src/backend/filters/AdvancedFilterBuilder.tsx +60 -34
- package/src/backend/injection/InjectedField.tsx +21 -12
- package/src/backend/inputs/ComboboxInput.tsx +4 -0
- package/src/backend/inputs/EventSelect.tsx +30 -17
- package/src/backend/inputs/PhoneNumberField.tsx +2 -2
- package/src/backend/inputs/TimeInput.tsx +9 -10
- package/src/backend/messages/message-compose-form-groups.tsx +21 -12
- package/src/backend/messages/useMessageCompose.ts +20 -1
- package/src/frontend/LanguageSwitcher.tsx +20 -17
- package/src/index.ts +5 -0
- package/src/primitives/checkbox-field.tsx +10 -2
- package/src/primitives/input.tsx +73 -12
- package/src/primitives/radio-field.tsx +92 -0
- package/src/primitives/radio.tsx +42 -0
- package/src/primitives/select.tsx +200 -0
- package/src/primitives/switch-field.tsx +100 -0
- package/src/primitives/switch.tsx +17 -4
- package/src/primitives/textarea.tsx +67 -11
- package/src/primitives/tooltip.tsx +68 -24
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/primitives/input.tsx"],
|
|
4
|
-
"sourcesContent": ["import * as React from 'react'\nimport { cn } from '@open-mercato/shared/lib/utils'\n\
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["import * as React from 'react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@open-mercato/shared/lib/utils'\n\nconst inputWrapperVariants = cva(\n 'inline-flex w-full items-center gap-2 rounded-md border border-input bg-background shadow-xs transition-colors focus-within:outline-none focus-within:shadow-focus focus-within:border-foreground hover:bg-muted/40 has-[input:disabled]:bg-bg-disabled has-[input:disabled]:border-border-disabled has-[input:disabled]:shadow-none has-[input:disabled]:hover:bg-bg-disabled has-[input[aria-invalid=true]]:border-destructive has-[input[aria-invalid=true]]:focus-within:border-destructive',\n {\n variants: {\n size: {\n sm: 'h-8 px-2.5',\n default: 'h-9 px-3',\n lg: 'h-10 px-3',\n },\n },\n defaultVariants: {\n size: 'default',\n },\n }\n)\n\nconst inputElementVariants = cva(\n 'flex-1 min-w-0 bg-transparent border-0 outline-none placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:bg-transparent',\n {\n variants: {\n size: {\n sm: 'text-xs',\n default: 'text-sm',\n lg: 'text-sm',\n },\n },\n defaultVariants: {\n size: 'default',\n },\n }\n)\n\nexport type InputProps = Omit<React.ComponentPropsWithoutRef<'input'>, 'size'> &\n VariantProps<typeof inputWrapperVariants> & {\n leftIcon?: React.ReactNode\n rightIcon?: React.ReactNode\n /** Optional className on the inner <input> element. */\n inputClassName?: string\n }\n\nexport const Input = React.forwardRef<HTMLInputElement, InputProps>(\n ({ className, inputClassName, type = 'text', size, leftIcon, rightIcon, ...props }, ref) => {\n return (\n <div\n className={cn(inputWrapperVariants({ size }), className)}\n data-slot=\"input-wrapper\"\n >\n {leftIcon ? (\n <span\n className=\"flex shrink-0 items-center text-muted-foreground [&_svg]:size-4\"\n aria-hidden=\"true\"\n >\n {leftIcon}\n </span>\n ) : null}\n <input\n ref={ref}\n type={type}\n className={cn(inputElementVariants({ size }), inputClassName)}\n {...props}\n />\n {rightIcon ? (\n <span\n className=\"flex shrink-0 items-center text-muted-foreground [&_svg]:size-4\"\n aria-hidden=\"true\"\n >\n {rightIcon}\n </span>\n ) : null}\n </div>\n )\n }\n)\n\nInput.displayName = 'Input'\n\nexport { inputWrapperVariants, inputElementVariants }\n"],
|
|
5
|
+
"mappings": "AA+CM,SAKI,KALJ;AA/CN,YAAY,WAAW;AACvB,SAAS,WAA8B;AACvC,SAAS,UAAU;AAEnB,MAAM,uBAAuB;AAAA,EAC3B;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,MAAM;AAAA,QACJ,IAAI;AAAA,QACJ,SAAS;AAAA,QACT,IAAI;AAAA,MACN;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,MACf,MAAM;AAAA,IACR;AAAA,EACF;AACF;AAEA,MAAM,uBAAuB;AAAA,EAC3B;AAAA,EACA;AAAA,IACE,UAAU;AAAA,MACR,MAAM;AAAA,QACJ,IAAI;AAAA,QACJ,SAAS;AAAA,QACT,IAAI;AAAA,MACN;AAAA,IACF;AAAA,IACA,iBAAiB;AAAA,MACf,MAAM;AAAA,IACR;AAAA,EACF;AACF;AAUO,MAAM,QAAQ,MAAM;AAAA,EACzB,CAAC,EAAE,WAAW,gBAAgB,OAAO,QAAQ,MAAM,UAAU,WAAW,GAAG,MAAM,GAAG,QAAQ;AAC1F,WACE;AAAA,MAAC;AAAA;AAAA,QACC,WAAW,GAAG,qBAAqB,EAAE,KAAK,CAAC,GAAG,SAAS;AAAA,QACvD,aAAU;AAAA,QAET;AAAA,qBACC;AAAA,YAAC;AAAA;AAAA,cACC,WAAU;AAAA,cACV,eAAY;AAAA,cAEX;AAAA;AAAA,UACH,IACE;AAAA,UACJ;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA;AAAA,cACA,WAAW,GAAG,qBAAqB,EAAE,KAAK,CAAC,GAAG,cAAc;AAAA,cAC3D,GAAG;AAAA;AAAA,UACN;AAAA,UACC,YACC;AAAA,YAAC;AAAA;AAAA,cACC,WAAU;AAAA,cACV,eAAY;AAAA,cAEX;AAAA;AAAA,UACH,IACE;AAAA;AAAA;AAAA,IACN;AAAA,EAEJ;AACF;AAEA,MAAM,cAAc;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { cn } from "@open-mercato/shared/lib/utils";
|
|
5
|
+
import { Radio } from "./radio.js";
|
|
6
|
+
const RadioField = React.forwardRef(({
|
|
7
|
+
id: idProp,
|
|
8
|
+
label,
|
|
9
|
+
sublabel,
|
|
10
|
+
description,
|
|
11
|
+
badge,
|
|
12
|
+
link,
|
|
13
|
+
flip = false,
|
|
14
|
+
containerClassName,
|
|
15
|
+
contentClassName,
|
|
16
|
+
className,
|
|
17
|
+
disabled,
|
|
18
|
+
...radioProps
|
|
19
|
+
}, ref) => {
|
|
20
|
+
const fallbackId = React.useId();
|
|
21
|
+
const id = idProp ?? fallbackId;
|
|
22
|
+
const hasMultiLine = Boolean(description || sublabel || link);
|
|
23
|
+
const radio = /* @__PURE__ */ jsx(
|
|
24
|
+
Radio,
|
|
25
|
+
{
|
|
26
|
+
ref,
|
|
27
|
+
id,
|
|
28
|
+
disabled,
|
|
29
|
+
className: cn(hasMultiLine && "mt-0.5", className),
|
|
30
|
+
...radioProps
|
|
31
|
+
}
|
|
32
|
+
);
|
|
33
|
+
const content = /* @__PURE__ */ jsxs("div", { className: cn("flex flex-1 min-w-0 flex-col gap-2.5", contentClassName), children: [
|
|
34
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
35
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
36
|
+
/* @__PURE__ */ jsx(
|
|
37
|
+
"label",
|
|
38
|
+
{
|
|
39
|
+
htmlFor: id,
|
|
40
|
+
className: cn(
|
|
41
|
+
"text-sm font-medium leading-5 text-foreground select-none",
|
|
42
|
+
disabled ? "cursor-not-allowed opacity-60" : "cursor-pointer"
|
|
43
|
+
),
|
|
44
|
+
children: label
|
|
45
|
+
}
|
|
46
|
+
),
|
|
47
|
+
sublabel ? /* @__PURE__ */ jsx("span", { className: "text-xs leading-4 text-muted-foreground select-none", children: sublabel }) : null,
|
|
48
|
+
badge ? /* @__PURE__ */ jsx("span", { className: "inline-flex shrink-0", children: badge }) : null
|
|
49
|
+
] }),
|
|
50
|
+
description ? /* @__PURE__ */ jsx("p", { className: "text-xs leading-4 text-muted-foreground", children: description }) : null
|
|
51
|
+
] }),
|
|
52
|
+
link ? /* @__PURE__ */ jsx("div", { className: "flex", children: link }) : null
|
|
53
|
+
] });
|
|
54
|
+
return /* @__PURE__ */ jsxs(
|
|
55
|
+
"div",
|
|
56
|
+
{
|
|
57
|
+
className: cn(
|
|
58
|
+
"flex gap-2",
|
|
59
|
+
hasMultiLine ? "items-start" : "items-center",
|
|
60
|
+
flip && "flex-row-reverse",
|
|
61
|
+
containerClassName
|
|
62
|
+
),
|
|
63
|
+
children: [
|
|
64
|
+
flip ? content : radio,
|
|
65
|
+
flip ? radio : content
|
|
66
|
+
]
|
|
67
|
+
}
|
|
68
|
+
);
|
|
69
|
+
});
|
|
70
|
+
RadioField.displayName = "RadioField";
|
|
71
|
+
export {
|
|
72
|
+
RadioField
|
|
73
|
+
};
|
|
74
|
+
//# sourceMappingURL=radio-field.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/primitives/radio-field.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { Radio } from './radio'\n\nexport type RadioFieldProps = Omit<React.ComponentProps<typeof Radio>, 'id'> & {\n id?: string\n label: React.ReactNode\n sublabel?: React.ReactNode\n description?: React.ReactNode\n badge?: React.ReactNode\n link?: React.ReactNode\n /** When true, renders the radio on the right of the label content. */\n flip?: boolean\n containerClassName?: string\n contentClassName?: string\n}\n\nexport const RadioField = React.forwardRef<\n React.ElementRef<typeof Radio>,\n RadioFieldProps\n>(({\n id: idProp,\n label,\n sublabel,\n description,\n badge,\n link,\n flip = false,\n containerClassName,\n contentClassName,\n className,\n disabled,\n ...radioProps\n}, ref) => {\n // useId is SSR/HMR-stable; counter-based fallbacks drift on hydration.\n const fallbackId = React.useId()\n const id = idProp ?? fallbackId\n\n const hasMultiLine = Boolean(description || sublabel || link)\n const radio = (\n <Radio\n ref={ref}\n id={id}\n disabled={disabled}\n className={cn(hasMultiLine && 'mt-0.5', className)}\n {...radioProps}\n />\n )\n\n const content = (\n <div className={cn('flex flex-1 min-w-0 flex-col gap-2.5', contentClassName)}>\n <div className=\"flex flex-col gap-1\">\n <div className=\"flex flex-wrap items-center gap-1\">\n <label\n htmlFor={id}\n className={cn(\n 'text-sm font-medium leading-5 text-foreground select-none',\n disabled ? 'cursor-not-allowed opacity-60' : 'cursor-pointer'\n )}\n >\n {label}\n </label>\n {sublabel ? (\n <span className=\"text-xs leading-4 text-muted-foreground select-none\">{sublabel}</span>\n ) : null}\n {badge ? <span className=\"inline-flex shrink-0\">{badge}</span> : null}\n </div>\n {description ? (\n <p className=\"text-xs leading-4 text-muted-foreground\">{description}</p>\n ) : null}\n </div>\n {link ? <div className=\"flex\">{link}</div> : null}\n </div>\n )\n\n return (\n <div\n className={cn(\n 'flex gap-2',\n hasMultiLine ? 'items-start' : 'items-center',\n flip && 'flex-row-reverse',\n containerClassName\n )}\n >\n {flip ? content : radio}\n {flip ? radio : content}\n </div>\n )\n})\nRadioField.displayName = 'RadioField'\n"],
|
|
5
|
+
"mappings": ";AA0CI,cAYI,YAZJ;AAxCJ,YAAY,WAAW;AACvB,SAAS,UAAU;AACnB,SAAS,aAAa;AAef,MAAM,aAAa,MAAM,WAG9B,CAAC;AAAA,EACD,IAAI;AAAA,EACJ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAG,QAAQ;AAET,QAAM,aAAa,MAAM,MAAM;AAC/B,QAAM,KAAK,UAAU;AAErB,QAAM,eAAe,QAAQ,eAAe,YAAY,IAAI;AAC5D,QAAM,QACJ;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW,GAAG,gBAAgB,UAAU,SAAS;AAAA,MAChD,GAAG;AAAA;AAAA,EACN;AAGF,QAAM,UACJ,qBAAC,SAAI,WAAW,GAAG,wCAAwC,gBAAgB,GACzE;AAAA,yBAAC,SAAI,WAAU,uBACb;AAAA,2BAAC,SAAI,WAAU,qCACb;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,SAAS;AAAA,YACT,WAAW;AAAA,cACT;AAAA,cACA,WAAW,kCAAkC;AAAA,YAC/C;AAAA,YAEC;AAAA;AAAA,QACH;AAAA,QACC,WACC,oBAAC,UAAK,WAAU,uDAAuD,oBAAS,IAC9E;AAAA,QACH,QAAQ,oBAAC,UAAK,WAAU,wBAAwB,iBAAM,IAAU;AAAA,SACnE;AAAA,MACC,cACC,oBAAC,OAAE,WAAU,2CAA2C,uBAAY,IAClE;AAAA,OACN;AAAA,IACC,OAAO,oBAAC,SAAI,WAAU,QAAQ,gBAAK,IAAS;AAAA,KAC/C;AAGF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA,eAAe,gBAAgB;AAAA,QAC/B,QAAQ;AAAA,QACR;AAAA,MACF;AAAA,MAEC;AAAA,eAAO,UAAU;AAAA,QACjB,OAAO,QAAQ;AAAA;AAAA;AAAA,EAClB;AAEJ,CAAC;AACD,WAAW,cAAc;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import * as RadioGroupPrimitive from "@radix-ui/react-radio-group";
|
|
5
|
+
import { cn } from "@open-mercato/shared/lib/utils";
|
|
6
|
+
const RadioGroup = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
7
|
+
RadioGroupPrimitive.Root,
|
|
8
|
+
{
|
|
9
|
+
ref,
|
|
10
|
+
className: cn("flex flex-col gap-2", className),
|
|
11
|
+
...props
|
|
12
|
+
}
|
|
13
|
+
));
|
|
14
|
+
RadioGroup.displayName = RadioGroupPrimitive.Root.displayName;
|
|
15
|
+
const Radio = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
16
|
+
RadioGroupPrimitive.Item,
|
|
17
|
+
{
|
|
18
|
+
ref,
|
|
19
|
+
className: cn(
|
|
20
|
+
"aspect-square size-5 shrink-0 rounded-full border border-input bg-background",
|
|
21
|
+
"flex items-center justify-center transition-colors",
|
|
22
|
+
"hover:border-muted-foreground/40",
|
|
23
|
+
"data-[state=checked]:border-accent-indigo data-[state=checked]:bg-accent-indigo",
|
|
24
|
+
"focus-visible:outline-none focus-visible:shadow-focus",
|
|
25
|
+
"disabled:cursor-not-allowed disabled:opacity-60",
|
|
26
|
+
className
|
|
27
|
+
),
|
|
28
|
+
...props,
|
|
29
|
+
children: /* @__PURE__ */ jsx(RadioGroupPrimitive.Indicator, { className: "flex items-center justify-center", children: /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "block size-2 rounded-full bg-white" }) })
|
|
30
|
+
}
|
|
31
|
+
));
|
|
32
|
+
Radio.displayName = RadioGroupPrimitive.Item.displayName;
|
|
33
|
+
export {
|
|
34
|
+
Radio,
|
|
35
|
+
RadioGroup
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=radio.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/primitives/radio.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport * as RadioGroupPrimitive from '@radix-ui/react-radio-group'\n\nimport { cn } from '@open-mercato/shared/lib/utils'\n\nexport const RadioGroup = React.forwardRef<\n React.ElementRef<typeof RadioGroupPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Root>\n>(({ className, ...props }, ref) => (\n <RadioGroupPrimitive.Root\n ref={ref}\n className={cn('flex flex-col gap-2', className)}\n {...props}\n />\n))\nRadioGroup.displayName = RadioGroupPrimitive.Root.displayName\n\nexport const Radio = React.forwardRef<\n React.ElementRef<typeof RadioGroupPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof RadioGroupPrimitive.Item>\n>(({ className, ...props }, ref) => (\n <RadioGroupPrimitive.Item\n ref={ref}\n className={cn(\n 'aspect-square size-5 shrink-0 rounded-full border border-input bg-background',\n 'flex items-center justify-center transition-colors',\n 'hover:border-muted-foreground/40',\n 'data-[state=checked]:border-accent-indigo data-[state=checked]:bg-accent-indigo',\n 'focus-visible:outline-none focus-visible:shadow-focus',\n 'disabled:cursor-not-allowed disabled:opacity-60',\n className\n )}\n {...props}\n >\n <RadioGroupPrimitive.Indicator className=\"flex items-center justify-center\">\n <span aria-hidden=\"true\" className=\"block size-2 rounded-full bg-white\" />\n </RadioGroupPrimitive.Indicator>\n </RadioGroupPrimitive.Item>\n))\nRadio.displayName = RadioGroupPrimitive.Item.displayName\n"],
|
|
5
|
+
"mappings": ";AAWE;AATF,YAAY,WAAW;AACvB,YAAY,yBAAyB;AAErC,SAAS,UAAU;AAEZ,MAAM,aAAa,MAAM,WAG9B,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B;AAAA,EAAC,oBAAoB;AAAA,EAApB;AAAA,IACC;AAAA,IACA,WAAW,GAAG,uBAAuB,SAAS;AAAA,IAC7C,GAAG;AAAA;AACN,CACD;AACD,WAAW,cAAc,oBAAoB,KAAK;AAE3C,MAAM,QAAQ,MAAM,WAGzB,CAAC,EAAE,WAAW,GAAG,MAAM,GAAG,QAC1B;AAAA,EAAC,oBAAoB;AAAA,EAApB;AAAA,IACC;AAAA,IACA,WAAW;AAAA,MACT;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,IACC,GAAG;AAAA,IAEJ,8BAAC,oBAAoB,WAApB,EAA8B,WAAU,oCACvC,8BAAC,UAAK,eAAY,QAAO,WAAU,sCAAqC,GAC1E;AAAA;AACF,CACD;AACD,MAAM,cAAc,oBAAoB,KAAK;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import * as SelectPrimitive from "@radix-ui/react-select";
|
|
5
|
+
import { Check, ChevronDown, ChevronUp } from "lucide-react";
|
|
6
|
+
import { cva } from "class-variance-authority";
|
|
7
|
+
import { cn } from "@open-mercato/shared/lib/utils";
|
|
8
|
+
const selectTriggerVariants = cva(
|
|
9
|
+
"inline-flex w-full items-center justify-between gap-2 rounded-md border border-input bg-background shadow-xs transition-colors outline-none placeholder:text-muted-foreground hover:bg-muted/40 focus:outline-none focus-visible:outline-none focus-visible:shadow-focus focus-visible:border-foreground disabled:cursor-not-allowed disabled:bg-bg-disabled disabled:border-border-disabled disabled:shadow-none disabled:hover:bg-bg-disabled disabled:[&_svg]:opacity-60 aria-[invalid=true]:border-destructive aria-[invalid=true]:focus-visible:border-destructive data-[placeholder]:text-muted-foreground [&>span]:line-clamp-1 [&_svg]:pointer-events-none [&_svg:not([class*=size-])]:size-4 [&_svg]:shrink-0",
|
|
10
|
+
{
|
|
11
|
+
variants: {
|
|
12
|
+
size: {
|
|
13
|
+
sm: "h-8 px-2.5 text-xs",
|
|
14
|
+
default: "h-9 px-3 text-sm",
|
|
15
|
+
lg: "h-10 px-3 text-sm"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
defaultVariants: {
|
|
19
|
+
size: "default"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
);
|
|
23
|
+
const SelectTrigger = React.forwardRef(({ className, size, children, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
24
|
+
SelectPrimitive.Trigger,
|
|
25
|
+
{
|
|
26
|
+
ref,
|
|
27
|
+
className: cn(selectTriggerVariants({ size }), className),
|
|
28
|
+
"data-slot": "select-trigger",
|
|
29
|
+
...props,
|
|
30
|
+
children: [
|
|
31
|
+
children,
|
|
32
|
+
/* @__PURE__ */ jsx(SelectPrimitive.Icon, { asChild: true, children: /* @__PURE__ */ jsx(ChevronDown, { className: "text-muted-foreground", "aria-hidden": "true" }) })
|
|
33
|
+
]
|
|
34
|
+
}
|
|
35
|
+
));
|
|
36
|
+
SelectTrigger.displayName = SelectPrimitive.Trigger.displayName;
|
|
37
|
+
const SelectScrollUpButton = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
38
|
+
SelectPrimitive.ScrollUpButton,
|
|
39
|
+
{
|
|
40
|
+
ref,
|
|
41
|
+
className: cn("flex cursor-default items-center justify-center py-1 text-muted-foreground", className),
|
|
42
|
+
...props,
|
|
43
|
+
children: /* @__PURE__ */ jsx(ChevronUp, { className: "size-4", "aria-hidden": "true" })
|
|
44
|
+
}
|
|
45
|
+
));
|
|
46
|
+
SelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName;
|
|
47
|
+
const SelectScrollDownButton = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
48
|
+
SelectPrimitive.ScrollDownButton,
|
|
49
|
+
{
|
|
50
|
+
ref,
|
|
51
|
+
className: cn("flex cursor-default items-center justify-center py-1 text-muted-foreground", className),
|
|
52
|
+
...props,
|
|
53
|
+
children: /* @__PURE__ */ jsx(ChevronDown, { className: "size-4", "aria-hidden": "true" })
|
|
54
|
+
}
|
|
55
|
+
));
|
|
56
|
+
SelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName;
|
|
57
|
+
const SelectContent = React.forwardRef(({ className, children, position = "popper", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ jsx(SelectPrimitive.Portal, { children: /* @__PURE__ */ jsxs(
|
|
58
|
+
SelectPrimitive.Content,
|
|
59
|
+
{
|
|
60
|
+
ref,
|
|
61
|
+
position,
|
|
62
|
+
sideOffset,
|
|
63
|
+
className: cn(
|
|
64
|
+
"relative z-dropdown min-w-[8rem] overflow-hidden rounded-md border border-input bg-popover text-popover-foreground shadow-md outline-none",
|
|
65
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
66
|
+
position === "popper" && "w-full min-w-[var(--radix-select-trigger-width)]",
|
|
67
|
+
className
|
|
68
|
+
),
|
|
69
|
+
...props,
|
|
70
|
+
children: [
|
|
71
|
+
/* @__PURE__ */ jsx(SelectScrollUpButton, {}),
|
|
72
|
+
/* @__PURE__ */ jsx(
|
|
73
|
+
SelectPrimitive.Viewport,
|
|
74
|
+
{
|
|
75
|
+
className: cn(
|
|
76
|
+
"p-1 max-h-[var(--radix-select-content-available-height)] overflow-y-auto",
|
|
77
|
+
position === "popper" && "w-full min-w-[var(--radix-select-trigger-width)]"
|
|
78
|
+
),
|
|
79
|
+
children
|
|
80
|
+
}
|
|
81
|
+
),
|
|
82
|
+
/* @__PURE__ */ jsx(SelectScrollDownButton, {})
|
|
83
|
+
]
|
|
84
|
+
}
|
|
85
|
+
) }));
|
|
86
|
+
SelectContent.displayName = SelectPrimitive.Content.displayName;
|
|
87
|
+
const SelectLabel = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
88
|
+
SelectPrimitive.Label,
|
|
89
|
+
{
|
|
90
|
+
ref,
|
|
91
|
+
className: cn("px-2 py-1.5 text-overline uppercase text-muted-foreground", className),
|
|
92
|
+
...props
|
|
93
|
+
}
|
|
94
|
+
));
|
|
95
|
+
SelectLabel.displayName = SelectPrimitive.Label.displayName;
|
|
96
|
+
const SelectItem = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
|
|
97
|
+
SelectPrimitive.Item,
|
|
98
|
+
{
|
|
99
|
+
ref,
|
|
100
|
+
className: cn(
|
|
101
|
+
"relative flex w-full cursor-default select-none items-center gap-2 rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none transition-colors",
|
|
102
|
+
"focus:bg-muted focus:text-foreground",
|
|
103
|
+
"data-[state=checked]:bg-muted/70 data-[state=checked]:text-foreground",
|
|
104
|
+
"data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
|
|
105
|
+
"[&_svg]:pointer-events-none [&_svg:not([class*=size-])]:size-4 [&_svg]:shrink-0",
|
|
106
|
+
className
|
|
107
|
+
),
|
|
108
|
+
...props,
|
|
109
|
+
children: [
|
|
110
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1 truncate", children: /* @__PURE__ */ jsx(SelectPrimitive.ItemText, { children }) }),
|
|
111
|
+
/* @__PURE__ */ jsx("span", { className: "absolute right-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ jsx(SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ jsx(Check, { className: "size-4 text-foreground", "aria-hidden": "true" }) }) })
|
|
112
|
+
]
|
|
113
|
+
}
|
|
114
|
+
));
|
|
115
|
+
SelectItem.displayName = SelectPrimitive.Item.displayName;
|
|
116
|
+
const SelectSeparator = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
117
|
+
SelectPrimitive.Separator,
|
|
118
|
+
{
|
|
119
|
+
ref,
|
|
120
|
+
className: cn("-mx-1 my-1 h-px bg-border", className),
|
|
121
|
+
...props
|
|
122
|
+
}
|
|
123
|
+
));
|
|
124
|
+
SelectSeparator.displayName = SelectPrimitive.Separator.displayName;
|
|
125
|
+
const Select = React.forwardRef(({ value, defaultValue, onValueChange, ...props }, _ref) => {
|
|
126
|
+
const isControlled = value !== void 0 || onValueChange !== void 0;
|
|
127
|
+
if (!isControlled) {
|
|
128
|
+
return /* @__PURE__ */ jsx(SelectPrimitive.Root, { defaultValue, ...props });
|
|
129
|
+
}
|
|
130
|
+
return /* @__PURE__ */ jsx(
|
|
131
|
+
SelectPrimitive.Root,
|
|
132
|
+
{
|
|
133
|
+
value: value ?? "",
|
|
134
|
+
onValueChange,
|
|
135
|
+
...props
|
|
136
|
+
}
|
|
137
|
+
);
|
|
138
|
+
});
|
|
139
|
+
Select.displayName = "Select";
|
|
140
|
+
const SelectGroup = SelectPrimitive.Group;
|
|
141
|
+
const SelectValue = SelectPrimitive.Value;
|
|
142
|
+
export {
|
|
143
|
+
Select,
|
|
144
|
+
SelectContent,
|
|
145
|
+
SelectGroup,
|
|
146
|
+
SelectItem,
|
|
147
|
+
SelectLabel,
|
|
148
|
+
SelectScrollDownButton,
|
|
149
|
+
SelectScrollUpButton,
|
|
150
|
+
SelectSeparator,
|
|
151
|
+
SelectTrigger,
|
|
152
|
+
SelectValue,
|
|
153
|
+
selectTriggerVariants
|
|
154
|
+
};
|
|
155
|
+
//# sourceMappingURL=select.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/primitives/select.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport * as SelectPrimitive from '@radix-ui/react-select'\nimport { Check, ChevronDown, ChevronUp } from 'lucide-react'\nimport { cva, type VariantProps } from 'class-variance-authority'\nimport { cn } from '@open-mercato/shared/lib/utils'\n\nconst selectTriggerVariants = cva(\n 'inline-flex w-full items-center justify-between gap-2 rounded-md border border-input bg-background shadow-xs transition-colors outline-none placeholder:text-muted-foreground hover:bg-muted/40 focus:outline-none focus-visible:outline-none focus-visible:shadow-focus focus-visible:border-foreground disabled:cursor-not-allowed disabled:bg-bg-disabled disabled:border-border-disabled disabled:shadow-none disabled:hover:bg-bg-disabled disabled:[&_svg]:opacity-60 aria-[invalid=true]:border-destructive aria-[invalid=true]:focus-visible:border-destructive data-[placeholder]:text-muted-foreground [&>span]:line-clamp-1 [&_svg]:pointer-events-none [&_svg:not([class*=size-])]:size-4 [&_svg]:shrink-0',\n {\n variants: {\n size: {\n sm: 'h-8 px-2.5 text-xs',\n default: 'h-9 px-3 text-sm',\n lg: 'h-10 px-3 text-sm',\n },\n },\n defaultVariants: {\n size: 'default',\n },\n }\n)\n\nexport type SelectTriggerProps = React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger> &\n VariantProps<typeof selectTriggerVariants>\n\nconst SelectTrigger = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Trigger>,\n SelectTriggerProps\n>(({ className, size, children, ...props }, ref) => (\n <SelectPrimitive.Trigger\n ref={ref}\n className={cn(selectTriggerVariants({ size }), className)}\n data-slot=\"select-trigger\"\n {...props}\n >\n {children}\n <SelectPrimitive.Icon asChild>\n <ChevronDown className=\"text-muted-foreground\" aria-hidden=\"true\" />\n </SelectPrimitive.Icon>\n </SelectPrimitive.Trigger>\n))\nSelectTrigger.displayName = SelectPrimitive.Trigger.displayName\n\nconst SelectScrollUpButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollUpButton\n ref={ref}\n className={cn('flex cursor-default items-center justify-center py-1 text-muted-foreground', className)}\n {...props}\n >\n <ChevronUp className=\"size-4\" aria-hidden=\"true\" />\n </SelectPrimitive.ScrollUpButton>\n))\nSelectScrollUpButton.displayName = SelectPrimitive.ScrollUpButton.displayName\n\nconst SelectScrollDownButton = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.ScrollDownButton\n ref={ref}\n className={cn('flex cursor-default items-center justify-center py-1 text-muted-foreground', className)}\n {...props}\n >\n <ChevronDown className=\"size-4\" aria-hidden=\"true\" />\n </SelectPrimitive.ScrollDownButton>\n))\nSelectScrollDownButton.displayName = SelectPrimitive.ScrollDownButton.displayName\n\nconst SelectContent = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>\n>(({ className, children, position = 'popper', sideOffset = 4, ...props }, ref) => (\n <SelectPrimitive.Portal>\n <SelectPrimitive.Content\n ref={ref}\n position={position}\n sideOffset={sideOffset}\n className={cn(\n 'relative z-dropdown min-w-[8rem] overflow-hidden rounded-md border border-input bg-popover text-popover-foreground shadow-md outline-none',\n 'data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n position === 'popper' && 'w-full min-w-[var(--radix-select-trigger-width)]',\n className\n )}\n {...props}\n >\n <SelectScrollUpButton />\n <SelectPrimitive.Viewport\n className={cn(\n 'p-1 max-h-[var(--radix-select-content-available-height)] overflow-y-auto',\n position === 'popper' && 'w-full min-w-[var(--radix-select-trigger-width)]'\n )}\n >\n {children}\n </SelectPrimitive.Viewport>\n <SelectScrollDownButton />\n </SelectPrimitive.Content>\n </SelectPrimitive.Portal>\n))\nSelectContent.displayName = SelectPrimitive.Content.displayName\n\nconst SelectLabel = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Label\n ref={ref}\n className={cn('px-2 py-1.5 text-overline uppercase text-muted-foreground', className)}\n {...props}\n />\n))\nSelectLabel.displayName = SelectPrimitive.Label.displayName\n\nconst SelectItem = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>\n>(({ className, children, ...props }, ref) => (\n <SelectPrimitive.Item\n ref={ref}\n className={cn(\n 'relative flex w-full cursor-default select-none items-center gap-2 rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none transition-colors',\n 'focus:bg-muted focus:text-foreground',\n 'data-[state=checked]:bg-muted/70 data-[state=checked]:text-foreground',\n 'data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n '[&_svg]:pointer-events-none [&_svg:not([class*=size-])]:size-4 [&_svg]:shrink-0',\n className\n )}\n {...props}\n >\n <span className=\"flex-1 truncate\">\n <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>\n </span>\n <span className=\"absolute right-2 flex h-3.5 w-3.5 items-center justify-center\">\n <SelectPrimitive.ItemIndicator>\n <Check className=\"size-4 text-foreground\" aria-hidden=\"true\" />\n </SelectPrimitive.ItemIndicator>\n </span>\n </SelectPrimitive.Item>\n))\nSelectItem.displayName = SelectPrimitive.Item.displayName\n\nconst SelectSeparator = React.forwardRef<\n React.ElementRef<typeof SelectPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <SelectPrimitive.Separator\n ref={ref}\n className={cn('-mx-1 my-1 h-px bg-border', className)}\n {...props}\n />\n))\nSelectSeparator.displayName = SelectPrimitive.Separator.displayName\n\n/**\n * Wraps Radix `Select.Root` to absorb the controlled/uncontrolled transition\n * many call sites trigger by passing `value={x || undefined}`. React fires\n * \"Select is changing from uncontrolled to controlled\" the moment value flips\n * from undefined to a defined string, and Radix's internal state ends up in\n * an inconsistent shape (dropdown flashes, selections no-op). Coercing\n * `undefined` \u2192 `''` keeps Radix in stable controlled mode for the lifetime\n * of the component while preserving \"no selection\" semantics \u2014 Radix simply\n * matches no SelectItem and `SelectValue` falls back to the placeholder.\n */\nconst Select = React.forwardRef<\n React.ComponentRef<typeof SelectPrimitive.Root>,\n React.ComponentPropsWithoutRef<typeof SelectPrimitive.Root>\n>(({ value, defaultValue, onValueChange, ...props }, _ref) => {\n const isControlled = value !== undefined || onValueChange !== undefined\n if (!isControlled) {\n return <SelectPrimitive.Root defaultValue={defaultValue} {...props} />\n }\n return (\n <SelectPrimitive.Root\n value={value ?? ''}\n onValueChange={onValueChange}\n {...props}\n />\n )\n}) as unknown as typeof SelectPrimitive.Root\n;(Select as React.ComponentType).displayName = 'Select'\nconst SelectGroup = SelectPrimitive.Group\nconst SelectValue = SelectPrimitive.Value\n\nexport {\n Select,\n SelectGroup,\n SelectValue,\n SelectTrigger,\n SelectContent,\n SelectLabel,\n SelectItem,\n SelectSeparator,\n SelectScrollUpButton,\n SelectScrollDownButton,\n selectTriggerVariants,\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { cn } from "@open-mercato/shared/lib/utils";
|
|
5
|
+
import { Switch } from "./switch.js";
|
|
6
|
+
const SwitchField = React.forwardRef(({
|
|
7
|
+
id: idProp,
|
|
8
|
+
label,
|
|
9
|
+
sublabel,
|
|
10
|
+
description,
|
|
11
|
+
badge,
|
|
12
|
+
link,
|
|
13
|
+
flip = false,
|
|
14
|
+
containerClassName,
|
|
15
|
+
contentClassName,
|
|
16
|
+
className,
|
|
17
|
+
disabled,
|
|
18
|
+
...switchProps
|
|
19
|
+
}, ref) => {
|
|
20
|
+
const fallbackId = React.useId();
|
|
21
|
+
const id = idProp ?? fallbackId;
|
|
22
|
+
const hasMultiLine = Boolean(description || sublabel || link);
|
|
23
|
+
const switchEl = /* @__PURE__ */ jsx(
|
|
24
|
+
Switch,
|
|
25
|
+
{
|
|
26
|
+
ref,
|
|
27
|
+
id,
|
|
28
|
+
disabled,
|
|
29
|
+
className: cn(hasMultiLine && "mt-0.5", className),
|
|
30
|
+
...switchProps
|
|
31
|
+
}
|
|
32
|
+
);
|
|
33
|
+
const content = /* @__PURE__ */ jsxs("div", { className: cn("flex flex-1 min-w-0 flex-col gap-2.5", contentClassName), children: [
|
|
34
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
35
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-1", children: [
|
|
36
|
+
/* @__PURE__ */ jsx(
|
|
37
|
+
"label",
|
|
38
|
+
{
|
|
39
|
+
htmlFor: id,
|
|
40
|
+
className: cn(
|
|
41
|
+
"text-sm font-medium leading-5 text-foreground select-none",
|
|
42
|
+
disabled ? "cursor-not-allowed opacity-60" : "cursor-pointer"
|
|
43
|
+
),
|
|
44
|
+
children: label
|
|
45
|
+
}
|
|
46
|
+
),
|
|
47
|
+
sublabel ? /* @__PURE__ */ jsx("span", { className: "text-xs leading-4 text-muted-foreground select-none", children: sublabel }) : null,
|
|
48
|
+
badge ? /* @__PURE__ */ jsx("span", { className: "inline-flex shrink-0", children: badge }) : null
|
|
49
|
+
] }),
|
|
50
|
+
description ? /* @__PURE__ */ jsx("p", { className: "text-xs leading-4 text-muted-foreground", children: description }) : null
|
|
51
|
+
] }),
|
|
52
|
+
link ? /* @__PURE__ */ jsx("div", { className: "flex", children: link }) : null
|
|
53
|
+
] });
|
|
54
|
+
return /* @__PURE__ */ jsx(
|
|
55
|
+
"div",
|
|
56
|
+
{
|
|
57
|
+
className: cn(
|
|
58
|
+
"flex gap-3",
|
|
59
|
+
hasMultiLine ? "items-start" : "items-center",
|
|
60
|
+
containerClassName
|
|
61
|
+
),
|
|
62
|
+
children: flip ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
63
|
+
switchEl,
|
|
64
|
+
content
|
|
65
|
+
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
66
|
+
content,
|
|
67
|
+
switchEl
|
|
68
|
+
] })
|
|
69
|
+
}
|
|
70
|
+
);
|
|
71
|
+
});
|
|
72
|
+
SwitchField.displayName = "SwitchField";
|
|
73
|
+
export {
|
|
74
|
+
SwitchField
|
|
75
|
+
};
|
|
76
|
+
//# sourceMappingURL=switch-field.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/primitives/switch-field.tsx"],
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { Switch } from './switch'\n\nexport type SwitchFieldProps = Omit<React.ComponentProps<typeof Switch>, 'id'> & {\n id?: string\n label: React.ReactNode\n sublabel?: React.ReactNode\n description?: React.ReactNode\n badge?: React.ReactNode\n link?: React.ReactNode\n /** When true, renders the switch on the left of the label content. */\n flip?: boolean\n containerClassName?: string\n contentClassName?: string\n}\n\nexport const SwitchField = React.forwardRef<\n React.ElementRef<typeof Switch>,\n SwitchFieldProps\n>(({\n id: idProp,\n label,\n sublabel,\n description,\n badge,\n link,\n flip = false,\n containerClassName,\n contentClassName,\n className,\n disabled,\n ...switchProps\n}, ref) => {\n // useId is SSR/HMR-stable; counter-based fallbacks drift on hydration.\n const fallbackId = React.useId()\n const id = idProp ?? fallbackId\n\n const hasMultiLine = Boolean(description || sublabel || link)\n const switchEl = (\n <Switch\n ref={ref}\n id={id}\n disabled={disabled}\n className={cn(hasMultiLine && 'mt-0.5', className)}\n {...switchProps}\n />\n )\n\n const content = (\n <div className={cn('flex flex-1 min-w-0 flex-col gap-2.5', contentClassName)}>\n <div className=\"flex flex-col gap-1\">\n <div className=\"flex flex-wrap items-center gap-1\">\n <label\n htmlFor={id}\n className={cn(\n 'text-sm font-medium leading-5 text-foreground select-none',\n disabled ? 'cursor-not-allowed opacity-60' : 'cursor-pointer'\n )}\n >\n {label}\n </label>\n {sublabel ? (\n <span className=\"text-xs leading-4 text-muted-foreground select-none\">{sublabel}</span>\n ) : null}\n {badge ? <span className=\"inline-flex shrink-0\">{badge}</span> : null}\n </div>\n {description ? (\n <p className=\"text-xs leading-4 text-muted-foreground\">{description}</p>\n ) : null}\n </div>\n {link ? <div className=\"flex\">{link}</div> : null}\n </div>\n )\n\n return (\n <div\n className={cn(\n 'flex gap-3',\n hasMultiLine ? 'items-start' : 'items-center',\n containerClassName\n )}\n >\n {flip ? (\n <>\n {switchEl}\n {content}\n </>\n ) : (\n <>\n {content}\n {switchEl}\n </>\n )}\n </div>\n )\n})\nSwitchField.displayName = 'SwitchField'\n"],
|
|
5
|
+
"mappings": ";AA0CI,SA4CI,UA5CJ,KAYI,YAZJ;AAxCJ,YAAY,WAAW;AACvB,SAAS,UAAU;AACnB,SAAS,cAAc;AAehB,MAAM,cAAc,MAAM,WAG/B,CAAC;AAAA,EACD,IAAI;AAAA,EACJ;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,OAAO;AAAA,EACP;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,GAAG;AACL,GAAG,QAAQ;AAET,QAAM,aAAa,MAAM,MAAM;AAC/B,QAAM,KAAK,UAAU;AAErB,QAAM,eAAe,QAAQ,eAAe,YAAY,IAAI;AAC5D,QAAM,WACJ;AAAA,IAAC;AAAA;AAAA,MACC;AAAA,MACA;AAAA,MACA;AAAA,MACA,WAAW,GAAG,gBAAgB,UAAU,SAAS;AAAA,MAChD,GAAG;AAAA;AAAA,EACN;AAGF,QAAM,UACJ,qBAAC,SAAI,WAAW,GAAG,wCAAwC,gBAAgB,GACzE;AAAA,yBAAC,SAAI,WAAU,uBACb;AAAA,2BAAC,SAAI,WAAU,qCACb;AAAA;AAAA,UAAC;AAAA;AAAA,YACC,SAAS;AAAA,YACT,WAAW;AAAA,cACT;AAAA,cACA,WAAW,kCAAkC;AAAA,YAC/C;AAAA,YAEC;AAAA;AAAA,QACH;AAAA,QACC,WACC,oBAAC,UAAK,WAAU,uDAAuD,oBAAS,IAC9E;AAAA,QACH,QAAQ,oBAAC,UAAK,WAAU,wBAAwB,iBAAM,IAAU;AAAA,SACnE;AAAA,MACC,cACC,oBAAC,OAAE,WAAU,2CAA2C,uBAAY,IAClE;AAAA,OACN;AAAA,IACC,OAAO,oBAAC,SAAI,WAAU,QAAQ,gBAAK,IAAS;AAAA,KAC/C;AAGF,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA,eAAe,gBAAgB;AAAA,QAC/B;AAAA,MACF;AAAA,MAEC,iBACC,iCACG;AAAA;AAAA,QACA;AAAA,SACH,IAEA,iCACG;AAAA;AAAA,QACA;AAAA,SACH;AAAA;AAAA,EAEJ;AAEJ,CAAC;AACD,YAAY,cAAc;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
"use client";
|
|
1
2
|
import { jsx } from "react/jsx-runtime";
|
|
2
3
|
import * as React from "react";
|
|
3
4
|
import { cn } from "@open-mercato/shared/lib/utils";
|
|
@@ -55,7 +56,9 @@ const Switch = React.forwardRef(
|
|
|
55
56
|
onKeyDown: handleKeyDown,
|
|
56
57
|
disabled,
|
|
57
58
|
className: cn(
|
|
58
|
-
"inline-flex h-
|
|
59
|
+
"group relative inline-flex h-5 w-8 shrink-0 cursor-pointer items-center justify-center rounded-full bg-transparent p-0",
|
|
60
|
+
"focus-visible:outline-none focus-visible:shadow-focus",
|
|
61
|
+
"disabled:cursor-not-allowed disabled:opacity-60",
|
|
59
62
|
className
|
|
60
63
|
),
|
|
61
64
|
...props,
|
|
@@ -64,8 +67,19 @@ const Switch = React.forwardRef(
|
|
|
64
67
|
{
|
|
65
68
|
"aria-hidden": true,
|
|
66
69
|
className: cn(
|
|
67
|
-
"
|
|
68
|
-
|
|
70
|
+
"pointer-events-none flex h-4 w-7 items-center rounded-full px-0.5 transition-colors duration-150",
|
|
71
|
+
"bg-border group-hover:bg-muted-foreground/30",
|
|
72
|
+
"group-data-[state=checked]:bg-accent-indigo group-data-[state=checked]:group-hover:bg-accent-indigo/85"
|
|
73
|
+
),
|
|
74
|
+
children: /* @__PURE__ */ jsx(
|
|
75
|
+
"span",
|
|
76
|
+
{
|
|
77
|
+
className: cn(
|
|
78
|
+
"block size-3 rounded-full bg-white transition-transform duration-200",
|
|
79
|
+
"shadow-[0_1px_2px_rgba(10,13,20,0.10),0_0_0_0.5px_rgba(10,13,20,0.04)]",
|
|
80
|
+
currentChecked ? "translate-x-3" : "translate-x-0"
|
|
81
|
+
)
|
|
82
|
+
}
|
|
69
83
|
)
|
|
70
84
|
}
|
|
71
85
|
)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/primitives/switch.tsx"],
|
|
4
|
-
"sourcesContent": ["
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\n\nimport { cn } from '@open-mercato/shared/lib/utils'\n\ntype SwitchProps = {\n checked?: boolean\n defaultChecked?: boolean\n onCheckedChange?: (checked: boolean) => void\n} & Omit<React.ComponentProps<'button'>, 'onChange'>\n\nexport const Switch = React.forwardRef<HTMLButtonElement, SwitchProps>(\n ({ checked, defaultChecked, onCheckedChange, disabled, className, onClick, onKeyDown, ...props }, ref) => {\n const isControlled = typeof checked === 'boolean'\n const [uncontrolledValue, setUncontrolledValue] = React.useState(defaultChecked ?? false)\n\n const currentChecked = isControlled ? checked : uncontrolledValue\n\n const toggle = React.useCallback(\n (event: React.MouseEvent<HTMLButtonElement> | React.KeyboardEvent<HTMLButtonElement>) => {\n event.preventDefault()\n if (disabled) {\n return\n }\n const next = !currentChecked\n if (!isControlled) {\n setUncontrolledValue(next)\n }\n onCheckedChange?.(next)\n },\n [currentChecked, disabled, isControlled, onCheckedChange]\n )\n\n const handleClick = React.useCallback(\n (event: React.MouseEvent<HTMLButtonElement>) => {\n onClick?.(event)\n if (!event.defaultPrevented) {\n toggle(event)\n }\n },\n [onClick, toggle]\n )\n\n const handleKeyDown = React.useCallback(\n (event: React.KeyboardEvent<HTMLButtonElement>) => {\n onKeyDown?.(event)\n if (event.defaultPrevented) {\n return\n }\n if (event.key === ' ' || event.key === 'Enter') {\n toggle(event)\n }\n },\n [onKeyDown, toggle]\n )\n\n return (\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked={currentChecked}\n aria-disabled={disabled}\n data-state={currentChecked ? 'checked' : 'unchecked'}\n data-disabled={disabled ? '' : undefined}\n ref={ref}\n onClick={handleClick}\n onKeyDown={handleKeyDown}\n disabled={disabled}\n className={cn(\n 'group relative inline-flex h-5 w-8 shrink-0 cursor-pointer items-center justify-center rounded-full bg-transparent p-0',\n 'focus-visible:outline-none focus-visible:shadow-focus',\n 'disabled:cursor-not-allowed disabled:opacity-60',\n className\n )}\n {...props}\n >\n <span\n aria-hidden\n className={cn(\n 'pointer-events-none flex h-4 w-7 items-center rounded-full px-0.5 transition-colors duration-150',\n 'bg-border group-hover:bg-muted-foreground/30',\n 'group-data-[state=checked]:bg-accent-indigo group-data-[state=checked]:group-hover:bg-accent-indigo/85'\n )}\n >\n <span\n className={cn(\n 'block size-3 rounded-full bg-white transition-transform duration-200',\n 'shadow-[0_1px_2px_rgba(10,13,20,0.10),0_0_0_0.5px_rgba(10,13,20,0.04)]',\n currentChecked ? 'translate-x-3' : 'translate-x-0'\n )}\n />\n </span>\n </button>\n )\n }\n)\n\nSwitch.displayName = 'Switch'\n"],
|
|
5
|
+
"mappings": ";AAqFU;AAnFV,YAAY,WAAW;AAEvB,SAAS,UAAU;AAQZ,MAAM,SAAS,MAAM;AAAA,EAC1B,CAAC,EAAE,SAAS,gBAAgB,iBAAiB,UAAU,WAAW,SAAS,WAAW,GAAG,MAAM,GAAG,QAAQ;AACxG,UAAM,eAAe,OAAO,YAAY;AACxC,UAAM,CAAC,mBAAmB,oBAAoB,IAAI,MAAM,SAAS,kBAAkB,KAAK;AAExF,UAAM,iBAAiB,eAAe,UAAU;AAEhD,UAAM,SAAS,MAAM;AAAA,MACnB,CAAC,UAAwF;AACvF,cAAM,eAAe;AACrB,YAAI,UAAU;AACZ;AAAA,QACF;AACA,cAAM,OAAO,CAAC;AACd,YAAI,CAAC,cAAc;AACjB,+BAAqB,IAAI;AAAA,QAC3B;AACA,0BAAkB,IAAI;AAAA,MACxB;AAAA,MACA,CAAC,gBAAgB,UAAU,cAAc,eAAe;AAAA,IAC1D;AAEA,UAAM,cAAc,MAAM;AAAA,MACxB,CAAC,UAA+C;AAC9C,kBAAU,KAAK;AACf,YAAI,CAAC,MAAM,kBAAkB;AAC3B,iBAAO,KAAK;AAAA,QACd;AAAA,MACF;AAAA,MACA,CAAC,SAAS,MAAM;AAAA,IAClB;AAEA,UAAM,gBAAgB,MAAM;AAAA,MAC1B,CAAC,UAAkD;AACjD,oBAAY,KAAK;AACjB,YAAI,MAAM,kBAAkB;AAC1B;AAAA,QACF;AACA,YAAI,MAAM,QAAQ,OAAO,MAAM,QAAQ,SAAS;AAC9C,iBAAO,KAAK;AAAA,QACd;AAAA,MACF;AAAA,MACA,CAAC,WAAW,MAAM;AAAA,IACpB;AAEA,WACE;AAAA,MAAC;AAAA;AAAA,QACC,MAAK;AAAA,QACL,MAAK;AAAA,QACL,gBAAc;AAAA,QACd,iBAAe;AAAA,QACf,cAAY,iBAAiB,YAAY;AAAA,QACzC,iBAAe,WAAW,KAAK;AAAA,QAC/B;AAAA,QACA,SAAS;AAAA,QACT,WAAW;AAAA,QACX;AAAA,QACA,WAAW;AAAA,UACT;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACC,GAAG;AAAA,QAEJ;AAAA,UAAC;AAAA;AAAA,YACC,eAAW;AAAA,YACX,WAAW;AAAA,cACT;AAAA,cACA;AAAA,cACA;AAAA,YACF;AAAA,YAEA;AAAA,cAAC;AAAA;AAAA,gBACC,WAAW;AAAA,kBACT;AAAA,kBACA;AAAA,kBACA,iBAAiB,kBAAkB;AAAA,gBACrC;AAAA;AAAA,YACF;AAAA;AAAA,QACF;AAAA;AAAA,IACF;AAAA,EAEJ;AACF;AAEA,OAAO,cAAc;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,18 +1,54 @@
|
|
|
1
|
-
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
3
|
import * as React from "react";
|
|
3
4
|
import { cn } from "@open-mercato/shared/lib/utils";
|
|
5
|
+
const baseTextareaClass = "flex w-full rounded-md border border-input bg-background px-3 py-2 text-sm shadow-xs transition-colors placeholder:text-muted-foreground outline-none focus-visible:outline-none focus-visible:shadow-focus focus-visible:border-foreground hover:bg-muted/40 disabled:cursor-not-allowed disabled:bg-bg-disabled disabled:border-border-disabled disabled:shadow-none disabled:hover:bg-bg-disabled aria-[invalid=true]:border-destructive aria-[invalid=true]:focus-visible:border-destructive resize-y min-h-[80px]";
|
|
4
6
|
const Textarea = React.forwardRef(
|
|
5
|
-
({ className, ...props }, ref) =>
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
)
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
7
|
+
({ className, showCount, wrapperClassName, value, defaultValue, maxLength, onChange, ...props }, ref) => {
|
|
8
|
+
const [internalValue, setInternalValue] = React.useState(
|
|
9
|
+
typeof defaultValue === "string" ? defaultValue : typeof value === "string" ? value : ""
|
|
10
|
+
);
|
|
11
|
+
const isControlled = value !== void 0;
|
|
12
|
+
const currentValue = isControlled ? String(value ?? "") : internalValue;
|
|
13
|
+
const handleChange = React.useCallback(
|
|
14
|
+
(event) => {
|
|
15
|
+
if (!isControlled) setInternalValue(event.target.value);
|
|
16
|
+
onChange?.(event);
|
|
17
|
+
},
|
|
18
|
+
[isControlled, onChange]
|
|
19
|
+
);
|
|
20
|
+
const textarea = /* @__PURE__ */ jsx(
|
|
21
|
+
"textarea",
|
|
22
|
+
{
|
|
23
|
+
ref,
|
|
24
|
+
value,
|
|
25
|
+
defaultValue: isControlled ? void 0 : defaultValue,
|
|
26
|
+
maxLength,
|
|
27
|
+
onChange: handleChange,
|
|
28
|
+
className: cn(baseTextareaClass, className),
|
|
29
|
+
...props
|
|
30
|
+
}
|
|
31
|
+
);
|
|
32
|
+
if (!showCount) return textarea;
|
|
33
|
+
const length = currentValue.length;
|
|
34
|
+
const max = typeof maxLength === "number" ? maxLength : void 0;
|
|
35
|
+
const isError = max != null && length > max;
|
|
36
|
+
const isDisabled = props.disabled;
|
|
37
|
+
return /* @__PURE__ */ jsxs("div", { className: cn("flex flex-col gap-1", wrapperClassName), children: [
|
|
38
|
+
textarea,
|
|
39
|
+
/* @__PURE__ */ jsx("div", { className: "flex justify-end", children: /* @__PURE__ */ jsx(
|
|
40
|
+
"span",
|
|
41
|
+
{
|
|
42
|
+
className: cn(
|
|
43
|
+
"text-overline uppercase",
|
|
44
|
+
isDisabled ? "text-text-disabled" : isError ? "text-destructive" : "text-muted-foreground"
|
|
45
|
+
),
|
|
46
|
+
"aria-live": "polite",
|
|
47
|
+
children: max != null ? `${length}/${max}` : `${length}`
|
|
48
|
+
}
|
|
49
|
+
) })
|
|
50
|
+
] });
|
|
51
|
+
}
|
|
16
52
|
);
|
|
17
53
|
Textarea.displayName = "Textarea";
|
|
18
54
|
export {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/primitives/textarea.tsx"],
|
|
4
|
-
"sourcesContent": ["
|
|
5
|
-
"mappings": "
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\n\nimport { cn } from '@open-mercato/shared/lib/utils'\n\nconst baseTextareaClass =\n 'flex w-full rounded-md border border-input bg-background px-3 py-2 text-sm shadow-xs transition-colors placeholder:text-muted-foreground outline-none focus-visible:outline-none focus-visible:shadow-focus focus-visible:border-foreground hover:bg-muted/40 disabled:cursor-not-allowed disabled:bg-bg-disabled disabled:border-border-disabled disabled:shadow-none disabled:hover:bg-bg-disabled aria-[invalid=true]:border-destructive aria-[invalid=true]:focus-visible:border-destructive resize-y min-h-[80px]'\n\nexport type TextareaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement> & {\n /** Show character counter (`current/max`) below the textarea. Requires `maxLength`. */\n showCount?: boolean\n /** Optional className applied to the outer wrapper (when counter is shown). */\n wrapperClassName?: string\n}\n\nexport const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(\n ({ className, showCount, wrapperClassName, value, defaultValue, maxLength, onChange, ...props }, ref) => {\n const [internalValue, setInternalValue] = React.useState<string>(\n typeof defaultValue === 'string' ? defaultValue : typeof value === 'string' ? value : ''\n )\n\n const isControlled = value !== undefined\n const currentValue = isControlled ? String(value ?? '') : internalValue\n\n const handleChange = React.useCallback(\n (event: React.ChangeEvent<HTMLTextAreaElement>) => {\n if (!isControlled) setInternalValue(event.target.value)\n onChange?.(event)\n },\n [isControlled, onChange]\n )\n\n const textarea = (\n <textarea\n ref={ref}\n value={value}\n defaultValue={isControlled ? undefined : defaultValue}\n maxLength={maxLength}\n onChange={handleChange}\n className={cn(baseTextareaClass, className)}\n {...props}\n />\n )\n\n if (!showCount) return textarea\n\n const length = currentValue.length\n const max = typeof maxLength === 'number' ? maxLength : undefined\n const isError = max != null && length > max\n const isDisabled = props.disabled\n\n return (\n <div className={cn('flex flex-col gap-1', wrapperClassName)}>\n {textarea}\n <div className=\"flex justify-end\">\n <span\n className={cn(\n 'text-overline uppercase',\n isDisabled\n ? 'text-text-disabled'\n : isError\n ? 'text-destructive'\n : 'text-muted-foreground'\n )}\n aria-live=\"polite\"\n >\n {max != null ? `${length}/${max}` : `${length}`}\n </span>\n </div>\n </div>\n )\n }\n)\n\nTextarea.displayName = 'Textarea'\n"],
|
|
5
|
+
"mappings": ";AAkCM,cAmBA,YAnBA;AAhCN,YAAY,WAAW;AAEvB,SAAS,UAAU;AAEnB,MAAM,oBACJ;AASK,MAAM,WAAW,MAAM;AAAA,EAC5B,CAAC,EAAE,WAAW,WAAW,kBAAkB,OAAO,cAAc,WAAW,UAAU,GAAG,MAAM,GAAG,QAAQ;AACvG,UAAM,CAAC,eAAe,gBAAgB,IAAI,MAAM;AAAA,MAC9C,OAAO,iBAAiB,WAAW,eAAe,OAAO,UAAU,WAAW,QAAQ;AAAA,IACxF;AAEA,UAAM,eAAe,UAAU;AAC/B,UAAM,eAAe,eAAe,OAAO,SAAS,EAAE,IAAI;AAE1D,UAAM,eAAe,MAAM;AAAA,MACzB,CAAC,UAAkD;AACjD,YAAI,CAAC,aAAc,kBAAiB,MAAM,OAAO,KAAK;AACtD,mBAAW,KAAK;AAAA,MAClB;AAAA,MACA,CAAC,cAAc,QAAQ;AAAA,IACzB;AAEA,UAAM,WACJ;AAAA,MAAC;AAAA;AAAA,QACC;AAAA,QACA;AAAA,QACA,cAAc,eAAe,SAAY;AAAA,QACzC;AAAA,QACA,UAAU;AAAA,QACV,WAAW,GAAG,mBAAmB,SAAS;AAAA,QACzC,GAAG;AAAA;AAAA,IACN;AAGF,QAAI,CAAC,UAAW,QAAO;AAEvB,UAAM,SAAS,aAAa;AAC5B,UAAM,MAAM,OAAO,cAAc,WAAW,YAAY;AACxD,UAAM,UAAU,OAAO,QAAQ,SAAS;AACxC,UAAM,aAAa,MAAM;AAEzB,WACE,qBAAC,SAAI,WAAW,GAAG,uBAAuB,gBAAgB,GACvD;AAAA;AAAA,MACD,oBAAC,SAAI,WAAU,oBACb;AAAA,QAAC;AAAA;AAAA,UACC,WAAW;AAAA,YACT;AAAA,YACA,aACI,uBACA,UACE,qBACA;AAAA,UACR;AAAA,UACA,aAAU;AAAA,UAET,iBAAO,OAAO,GAAG,MAAM,IAAI,GAAG,KAAK,GAAG,MAAM;AAAA;AAAA,MAC/C,GACF;AAAA,OACF;AAAA,EAEJ;AACF;AAEA,SAAS,cAAc;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|