@pipe0/react 0.0.7 → 0.0.9

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/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @pipe0/elements-react
2
2
 
3
+ ## 0.0.9
4
+
5
+ ### Patch Changes
6
+
7
+ - v1 preparations
8
+ - Updated dependencies
9
+ - @pipe0/base@0.0.9
10
+
11
+ ## 0.0.8
12
+
13
+ ### Patch Changes
14
+
15
+ - Update billing info
16
+ - Updated dependencies
17
+ - @pipe0/base@0.0.8
18
+
3
19
  ## 0.0.7
4
20
 
5
21
  ### Patch Changes
@@ -53,6 +53,7 @@ function ConnectorInputAdapter(field) {
53
53
  type: "button",
54
54
  variant: "link",
55
55
  size: "xs",
56
+ className: "pz:px-0",
56
57
  onClick: () => field.setValue({ connections: [] }),
57
58
  children: [/* @__PURE__ */ jsx(IconPlus, {}), "Add custom connection"]
58
59
  })
@@ -1 +1 @@
1
- {"version":3,"file":"connector-input.mjs","names":[],"sources":["../../../../src/components/defaults/adapters/connector-input.tsx"],"sourcesContent":["import type { ProviderName } from \"@pipe0/base\";\nimport { useMemo } from \"react\";\nimport { useFieldError } from \"../../../hooks/use-field-error.js\";\nimport { cn } from \"../../../lib/utils.js\";\nimport type { FieldHandle } from \"../../../types/field-handle.js\";\nimport { ProviderLogo } from \"../../../widgets/provider-logo.js\";\nimport { SuggestCombobox } from \"../../internal/combobox/suggest-combobox.js\";\nimport { IconPlus } from \"../../internal/icons.js\";\nimport { Button } from \"../../ui/button.js\";\n\nexport function ConnectorInputAdapter(field: FieldHandle<\"connector_input\">) {\n const connections = field.meta.filteredConnections ?? [];\n const value = field.value ?? null;\n const current = value?.connections ?? [];\n const error = useFieldError(field.form, field.path);\n const hasError = !!error;\n\n const options = useMemo(\n () =>\n connections.map((c) => ({\n value: c.connection,\n label: c.connection,\n })),\n [connections],\n );\n\n const providerByConnection = useMemo(() => {\n const map = new Map<string, string>();\n for (const c of connections) map.set(c.connection, c.provider);\n return map;\n }, [connections]);\n\n const renderLogo = (connectionId: string) => {\n const provider = providerByConnection.get(connectionId);\n if (!provider) return null;\n return <ProviderLogo provider={provider as ProviderName} size={16} />;\n };\n\n if (field.meta.connectorMode === \"disabled\") {\n return (\n <div\n data-p0=\"input\"\n className=\"pz:flex pz:items-center pz:rounded-md pz:border pz:border-input pz:bg-muted pz:px-3 pz:py-2 pz:opacity-60\"\n >\n <span className=\"pz:text-sm pz:text-muted-foreground\">\n Custom connections are not supported for this pipe.\n </span>\n </div>\n );\n }\n\n if (connections.length === 0) {\n return (\n <div\n data-p0=\"input\"\n className=\"pz:flex pz:flex-col pz:gap-2 pz:rounded-md pz:border pz:border-input pz:bg-transparent pz:px-3 pz:py-2\"\n >\n <span className=\"pz:text-xs pz:text-muted-foreground\">No connections available.</span>\n </div>\n );\n }\n\n if (value == null) {\n return (\n <div data-p0=\"input\" className=\"pz:flex pz:items-center\">\n <Button\n type=\"button\"\n variant=\"link\"\n size=\"xs\"\n onClick={() => field.setValue({ connections: [] })}\n >\n <IconPlus />\n Add custom connection\n </Button>\n </div>\n );\n }\n\n return (\n <div data-p0=\"input\" className=\"pz:flex pz:flex-col pz:gap-1\">\n <div className={cn(hasError && \"pz:[&_[data-slot=combobox-chips]]:border-destructive\")}>\n <SuggestCombobox\n value={current.map((c) => c.connection)}\n onChange={(next) =>\n field.setValue({\n ...value,\n connections: next.map((connection) => ({\n type: \"vault\",\n connection,\n })),\n })\n }\n options={options}\n iconFor={renderLogo}\n ariaInvalid={hasError}\n placeholder=\"Select a connection\"\n />\n </div>\n <div className=\"pz:flex pz:items-center pz:justify-end\">\n <Button type=\"button\" variant=\"link\" size=\"xs\" onClick={() => field.setValue(null)}>\n Reset\n </Button>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;AAUA,SAAgB,sBAAsB,OAAuC;CAC3E,MAAM,cAAc,MAAM,KAAK,uBAAuB,EAAE;CACxD,MAAM,QAAQ,MAAM,SAAS;CAC7B,MAAM,UAAU,OAAO,eAAe,EAAE;CAExC,MAAM,WAAW,CAAC,CADJ,cAAc,MAAM,MAAM,MAAM,KAAK;CAGnD,MAAM,UAAU,cAEZ,YAAY,KAAK,OAAO;EACtB,OAAO,EAAE;EACT,OAAO,EAAE;EACV,EAAE,EACL,CAAC,YAAY,CACd;CAED,MAAM,uBAAuB,cAAc;EACzC,MAAM,sBAAM,IAAI,KAAqB;AACrC,OAAK,MAAM,KAAK,YAAa,KAAI,IAAI,EAAE,YAAY,EAAE,SAAS;AAC9D,SAAO;IACN,CAAC,YAAY,CAAC;CAEjB,MAAM,cAAc,iBAAyB;EAC3C,MAAM,WAAW,qBAAqB,IAAI,aAAa;AACvD,MAAI,CAAC,SAAU,QAAO;AACtB,SAAO,oBAAC,cAAD;GAAwB;GAA0B,MAAM;GAAM;;AAGvE,KAAI,MAAM,KAAK,kBAAkB,WAC/B,QACE,oBAAC,OAAD;EACE,WAAQ;EACR,WAAU;YAEV,oBAAC,QAAD;GAAM,WAAU;aAAsC;GAE/C;EACH;AAIV,KAAI,YAAY,WAAW,EACzB,QACE,oBAAC,OAAD;EACE,WAAQ;EACR,WAAU;YAEV,oBAAC,QAAD;GAAM,WAAU;aAAsC;GAAgC;EAClF;AAIV,KAAI,SAAS,KACX,QACE,oBAAC,OAAD;EAAK,WAAQ;EAAQ,WAAU;YAC7B,qBAAC,QAAD;GACE,MAAK;GACL,SAAQ;GACR,MAAK;GACL,eAAe,MAAM,SAAS,EAAE,aAAa,EAAE,EAAE,CAAC;aAJpD,CAME,oBAAC,UAAD,EAAY,2BAEL;;EACL;AAIV,QACE,qBAAC,OAAD;EAAK,WAAQ;EAAQ,WAAU;YAA/B,CACE,oBAAC,OAAD;GAAK,WAAW,GAAG,YAAY,uDAAuD;aACpF,oBAAC,iBAAD;IACE,OAAO,QAAQ,KAAK,MAAM,EAAE,WAAW;IACvC,WAAW,SACT,MAAM,SAAS;KACb,GAAG;KACH,aAAa,KAAK,KAAK,gBAAgB;MACrC,MAAM;MACN;MACD,EAAE;KACJ,CAAC;IAEK;IACT,SAAS;IACT,aAAa;IACb,aAAY;IACZ;GACE,GACN,oBAAC,OAAD;GAAK,WAAU;aACb,oBAAC,QAAD;IAAQ,MAAK;IAAS,SAAQ;IAAO,MAAK;IAAK,eAAe,MAAM,SAAS,KAAK;cAAE;IAE3E;GACL,EACF"}
1
+ {"version":3,"file":"connector-input.mjs","names":[],"sources":["../../../../src/components/defaults/adapters/connector-input.tsx"],"sourcesContent":["import type { ProviderName } from \"@pipe0/base\";\nimport { useMemo } from \"react\";\nimport { useFieldError } from \"../../../hooks/use-field-error.js\";\nimport { cn } from \"../../../lib/utils.js\";\nimport type { FieldHandle } from \"../../../types/field-handle.js\";\nimport { ProviderLogo } from \"../../../widgets/provider-logo.js\";\nimport { SuggestCombobox } from \"../../internal/combobox/suggest-combobox.js\";\nimport { IconPlus } from \"../../internal/icons.js\";\nimport { Button } from \"../../ui/button.js\";\n\nexport function ConnectorInputAdapter(field: FieldHandle<\"connector_input\">) {\n const connections = field.meta.filteredConnections ?? [];\n const value = field.value ?? null;\n const current = value?.connections ?? [];\n const error = useFieldError(field.form, field.path);\n const hasError = !!error;\n\n const options = useMemo(\n () =>\n connections.map((c) => ({\n value: c.connection,\n label: c.connection,\n })),\n [connections],\n );\n\n const providerByConnection = useMemo(() => {\n const map = new Map<string, string>();\n for (const c of connections) map.set(c.connection, c.provider);\n return map;\n }, [connections]);\n\n const renderLogo = (connectionId: string) => {\n const provider = providerByConnection.get(connectionId);\n if (!provider) return null;\n return <ProviderLogo provider={provider as ProviderName} size={16} />;\n };\n\n if (field.meta.connectorMode === \"disabled\") {\n return (\n <div\n data-p0=\"input\"\n className=\"pz:flex pz:items-center pz:rounded-md pz:border pz:border-input pz:bg-muted pz:px-3 pz:py-2 pz:opacity-60\"\n >\n <span className=\"pz:text-sm pz:text-muted-foreground\">\n Custom connections are not supported for this pipe.\n </span>\n </div>\n );\n }\n\n if (connections.length === 0) {\n return (\n <div\n data-p0=\"input\"\n className=\"pz:flex pz:flex-col pz:gap-2 pz:rounded-md pz:border pz:border-input pz:bg-transparent pz:px-3 pz:py-2\"\n >\n <span className=\"pz:text-xs pz:text-muted-foreground\">No connections available.</span>\n </div>\n );\n }\n\n if (value == null) {\n return (\n <div data-p0=\"input\" className=\"pz:flex pz:items-center\">\n <Button\n type=\"button\"\n variant=\"link\"\n size=\"xs\"\n className=\"pz:px-0\"\n onClick={() => field.setValue({ connections: [] })}\n >\n <IconPlus />\n Add custom connection\n </Button>\n </div>\n );\n }\n\n return (\n <div data-p0=\"input\" className=\"pz:flex pz:flex-col pz:gap-1\">\n <div className={cn(hasError && \"pz:[&_[data-slot=combobox-chips]]:border-destructive\")}>\n <SuggestCombobox\n value={current.map((c) => c.connection)}\n onChange={(next) =>\n field.setValue({\n ...value,\n connections: next.map((connection) => ({\n type: \"vault\",\n connection,\n })),\n })\n }\n options={options}\n iconFor={renderLogo}\n ariaInvalid={hasError}\n placeholder=\"Select a connection\"\n />\n </div>\n <div className=\"pz:flex pz:items-center pz:justify-end\">\n <Button type=\"button\" variant=\"link\" size=\"xs\" onClick={() => field.setValue(null)}>\n Reset\n </Button>\n </div>\n </div>\n );\n}\n"],"mappings":";;;;;;;;;;AAUA,SAAgB,sBAAsB,OAAuC;CAC3E,MAAM,cAAc,MAAM,KAAK,uBAAuB,EAAE;CACxD,MAAM,QAAQ,MAAM,SAAS;CAC7B,MAAM,UAAU,OAAO,eAAe,EAAE;CAExC,MAAM,WAAW,CAAC,CADJ,cAAc,MAAM,MAAM,MAAM,KAAK;CAGnD,MAAM,UAAU,cAEZ,YAAY,KAAK,OAAO;EACtB,OAAO,EAAE;EACT,OAAO,EAAE;EACV,EAAE,EACL,CAAC,YAAY,CACd;CAED,MAAM,uBAAuB,cAAc;EACzC,MAAM,sBAAM,IAAI,KAAqB;AACrC,OAAK,MAAM,KAAK,YAAa,KAAI,IAAI,EAAE,YAAY,EAAE,SAAS;AAC9D,SAAO;IACN,CAAC,YAAY,CAAC;CAEjB,MAAM,cAAc,iBAAyB;EAC3C,MAAM,WAAW,qBAAqB,IAAI,aAAa;AACvD,MAAI,CAAC,SAAU,QAAO;AACtB,SAAO,oBAAC,cAAD;GAAwB;GAA0B,MAAM;GAAM;;AAGvE,KAAI,MAAM,KAAK,kBAAkB,WAC/B,QACE,oBAAC,OAAD;EACE,WAAQ;EACR,WAAU;YAEV,oBAAC,QAAD;GAAM,WAAU;aAAsC;GAE/C;EACH;AAIV,KAAI,YAAY,WAAW,EACzB,QACE,oBAAC,OAAD;EACE,WAAQ;EACR,WAAU;YAEV,oBAAC,QAAD;GAAM,WAAU;aAAsC;GAAgC;EAClF;AAIV,KAAI,SAAS,KACX,QACE,oBAAC,OAAD;EAAK,WAAQ;EAAQ,WAAU;YAC7B,qBAAC,QAAD;GACE,MAAK;GACL,SAAQ;GACR,MAAK;GACL,WAAU;GACV,eAAe,MAAM,SAAS,EAAE,aAAa,EAAE,EAAE,CAAC;aALpD,CAOE,oBAAC,UAAD,EAAY,2BAEL;;EACL;AAIV,QACE,qBAAC,OAAD;EAAK,WAAQ;EAAQ,WAAU;YAA/B,CACE,oBAAC,OAAD;GAAK,WAAW,GAAG,YAAY,uDAAuD;aACpF,oBAAC,iBAAD;IACE,OAAO,QAAQ,KAAK,MAAM,EAAE,WAAW;IACvC,WAAW,SACT,MAAM,SAAS;KACb,GAAG;KACH,aAAa,KAAK,KAAK,gBAAgB;MACrC,MAAM;MACN;MACD,EAAE;KACJ,CAAC;IAEK;IACT,SAAS;IACT,aAAa;IACb,aAAY;IACZ;GACE,GACN,oBAAC,OAAD;GAAK,WAAU;aACb,oBAAC,QAAD;IAAQ,MAAK;IAAS,SAAQ;IAAO,MAAK;IAAK,eAAe,MAAM,SAAS,KAAK;cAAE;IAE3E;GACL,EACF"}
@@ -1,7 +1,9 @@
1
1
  import { cn } from "../../../lib/utils.mjs";
2
2
  import { IconGripVertical, IconPlus } from "../../internal/icons.mjs";
3
+ import { PricingBadge } from "../../../widgets/pricing-badge.mjs";
3
4
  import { WidgetStrip } from "../../../widgets/widget-strip.mjs";
4
5
  import { Popover, PopoverContent, PopoverTrigger } from "../../ui/popover.mjs";
6
+ import { AvatarGroup } from "../../../widgets/avatar-group.mjs";
5
7
  import { useMemo, useState } from "react";
6
8
  import { jsx, jsxs } from "react/jsx-runtime";
7
9
  import { Search, X } from "lucide-react";
@@ -11,15 +13,33 @@ import { SortableContext, useSortable, verticalListSortingStrategy } from "@dnd-
11
13
  //#region src/components/defaults/adapters/providers-input.tsx
12
14
  function splitWidgets(widgets) {
13
15
  if (!widgets) return {
16
+ providerName: void 0,
14
17
  leading: void 0,
15
18
  pricing: void 0
16
19
  };
17
- const { pricing, ...rest } = widgets;
20
+ const { pricing, provider_logo, ...rest } = widgets;
21
+ const hasLeading = Object.values(rest).some((v) => v != null);
18
22
  return {
19
- leading: Object.values(rest).some((v) => v != null) ? rest : void 0,
23
+ providerName: provider_logo?.provider,
24
+ leading: hasLeading ? rest : void 0,
20
25
  pricing
21
26
  };
22
27
  }
28
+ function LeadingAvatar({ providerName, leading }) {
29
+ if (providerName) return /* @__PURE__ */ jsx(AvatarGroup, {
30
+ providers: [providerName],
31
+ size: "sm",
32
+ className: "pz:shrink-0"
33
+ });
34
+ if (leading) return /* @__PURE__ */ jsx("span", {
35
+ className: "pz:flex pz:items-center pz:shrink-0",
36
+ children: /* @__PURE__ */ jsx(WidgetStrip, {
37
+ widgets: leading,
38
+ size: 18
39
+ })
40
+ });
41
+ return null;
42
+ }
23
43
  /**
24
44
  * Provider waterfall — vertical, ordered list of providers tried sequentially
25
45
  * until a valid result is returned. The list makes the running order legible
@@ -93,7 +113,7 @@ function ProviderRow({ value, index, label, widgets, onRemove }) {
93
113
  transition,
94
114
  opacity: isDragging ? .6 : 1
95
115
  };
96
- const { leading, pricing } = splitWidgets(widgets);
116
+ const { providerName, leading, pricing } = splitWidgets(widgets);
97
117
  const orderLabel = String(index + 1).padStart(2, "0");
98
118
  return /* @__PURE__ */ jsxs("li", {
99
119
  ref: setNodeRef,
@@ -111,21 +131,15 @@ function ProviderRow({ value, index, label, widgets, onRemove }) {
111
131
  height: 14
112
132
  })
113
133
  }),
114
- leading && /* @__PURE__ */ jsx("span", {
115
- className: "pz:flex pz:items-center pz:shrink-0",
116
- children: /* @__PURE__ */ jsx(WidgetStrip, {
117
- widgets: leading,
118
- size: 18
119
- })
134
+ /* @__PURE__ */ jsx(LeadingAvatar, {
135
+ providerName,
136
+ leading
120
137
  }),
121
138
  /* @__PURE__ */ jsx("span", {
122
139
  className: "pz:text-sm pz:font-medium pz:text-foreground pz:flex-1 pz:truncate",
123
140
  children: label
124
141
  }),
125
- pricing && /* @__PURE__ */ jsxs("span", {
126
- className: "pz:text-xs pz:text-muted-foreground pz:tabular-nums",
127
- children: [pricing.credits, " cr"]
128
- }),
142
+ pricing && /* @__PURE__ */ jsx(PricingBadge, { credits: pricing.credits }),
129
143
  /* @__PURE__ */ jsx("span", {
130
144
  "aria-hidden": true,
131
145
  className: cn("pz:inline-flex pz:items-center pz:justify-center pz:min-w-7 pz:h-5 pz:px-1.5", "pz:rounded-full pz:bg-muted pz:text-muted-foreground pz:text-[10.5px]", "pz:font-medium pz:tabular-nums"),
@@ -190,7 +204,7 @@ function AddProviderControl({ options, excluded, onAdd, ariaInvalid }) {
190
204
  className: "pz:px-2 pz:py-3 pz:text-center pz:text-xs pz:text-muted-foreground",
191
205
  children: "No providers"
192
206
  }), filtered.map((option) => {
193
- const { leading, pricing } = splitWidgets(option.widgets);
207
+ const { providerName, leading, pricing } = splitWidgets(option.widgets);
194
208
  return /* @__PURE__ */ jsx("li", {
195
209
  className: "pz:contents",
196
210
  children: /* @__PURE__ */ jsxs("button", {
@@ -202,21 +216,15 @@ function AddProviderControl({ options, excluded, onAdd, ariaInvalid }) {
202
216
  },
203
217
  className: cn("pz:flex pz:items-center pz:gap-2 pz:w-full pz:text-left", "pz:px-2 pz:py-1.5 pz:rounded-md pz:text-sm", "pz:hover:bg-accent pz:hover:text-accent-foreground", "pz:transition-colors pz:cursor-pointer"),
204
218
  children: [
205
- leading && /* @__PURE__ */ jsx("span", {
206
- className: "pz:flex pz:items-center pz:shrink-0",
207
- children: /* @__PURE__ */ jsx(WidgetStrip, {
208
- widgets: leading,
209
- size: 16
210
- })
219
+ /* @__PURE__ */ jsx(LeadingAvatar, {
220
+ providerName,
221
+ leading
211
222
  }),
212
223
  /* @__PURE__ */ jsx("span", {
213
224
  className: "pz:flex-1 pz:truncate",
214
225
  children: option.label
215
226
  }),
216
- pricing && /* @__PURE__ */ jsxs("span", {
217
- className: "pz:text-xs pz:text-muted-foreground pz:tabular-nums",
218
- children: [pricing.credits, " cr"]
219
- })
227
+ pricing && /* @__PURE__ */ jsx(PricingBadge, { credits: pricing.credits })
220
228
  ]
221
229
  })
222
230
  }, option.value);
@@ -1 +1 @@
1
- {"version":3,"file":"providers-input.mjs","names":["XIcon","SearchIcon"],"sources":["../../../../src/components/defaults/adapters/providers-input.tsx"],"sourcesContent":["import {\n closestCenter,\n DndContext,\n type DragEndEvent,\n KeyboardSensor,\n PointerSensor,\n useSensor,\n useSensors,\n} from \"@dnd-kit/core\";\nimport { SortableContext, useSortable, verticalListSortingStrategy } from \"@dnd-kit/sortable\";\nimport type { WidgetsByKind } from \"@pipe0/base\";\nimport { Search as SearchIcon, X as XIcon } from \"lucide-react\";\nimport { type CSSProperties, useMemo, useState } from \"react\";\nimport { cn } from \"../../../lib/utils.js\";\nimport type { FieldHandle } from \"../../../types/field-handle.js\";\nimport { WidgetStrip } from \"../../../widgets/widget-strip.js\";\nimport { IconGripVertical, IconPlus } from \"../../internal/icons.js\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../../ui/popover.js\";\n\ntype ProviderOption = {\n value: string;\n label: string;\n widgets?: WidgetsByKind;\n};\n\nfunction splitWidgets(widgets: WidgetsByKind | undefined): {\n leading: WidgetsByKind | undefined;\n pricing: WidgetsByKind[\"pricing\"] | undefined;\n} {\n if (!widgets) return { leading: undefined, pricing: undefined };\n const { pricing, ...rest } = widgets;\n const hasLeading = Object.values(rest).some((v) => v != null);\n return { leading: hasLeading ? rest : undefined, pricing };\n}\n\n/**\n * Provider waterfall — vertical, ordered list of providers tried sequentially\n * until a valid result is returned. The list makes the running order legible\n * (numeric badge per row, drag-to-reorder), and the credit widget per\n * provider stays visible.\n */\nexport function ProvidersInputAdapter(field: FieldHandle<\"providers_input\">) {\n const selected: string[] = useMemo(\n () => (field.value ?? []).map((p: { provider: string }) => p.provider),\n [field.value],\n );\n\n const options = field.options ?? [];\n const optionByValue = useMemo(() => {\n const map = new Map<string, ProviderOption>();\n for (const o of options) map.set(o.value, o);\n return map;\n }, [options]);\n\n const maxItems = field.meta.maxItems;\n const atMax = maxItems !== undefined && selected.length >= maxItems;\n\n const setValue = (next: string[]) =>\n field.setValue(next.map((provider) => ({ provider })));\n\n const handleRemove = (value: string) => setValue(selected.filter((v) => v !== value));\n const handleAdd = (value: string) => {\n if (selected.includes(value)) return;\n setValue([...selected, value]);\n };\n\n const sensors = useSensors(\n useSensor(PointerSensor, { activationConstraint: { distance: 4 } }),\n useSensor(KeyboardSensor),\n );\n\n const handleDragEnd = (event: DragEndEvent) => {\n const { active, over } = event;\n if (!over || active.id === over.id) return;\n const from = selected.indexOf(String(active.id));\n const to = selected.indexOf(String(over.id));\n if (from === -1 || to === -1) return;\n const next = [...selected];\n const [moved] = next.splice(from, 1);\n next.splice(to, 0, moved);\n setValue(next);\n };\n\n return (\n <div data-p0=\"input\" className=\"pz:flex pz:flex-col pz:gap-1\">\n {selected.length > 0 && (\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n onDragEnd={handleDragEnd}\n >\n <SortableContext items={selected} strategy={verticalListSortingStrategy}>\n <ul className=\"pz:flex pz:flex-col pz:gap-0.5 pz:list-none pz:m-0 pz:p-0\">\n {selected.map((value, index) => {\n const option = optionByValue.get(value);\n return (\n <ProviderRow\n key={value}\n value={value}\n index={index}\n label={option?.label ?? value}\n widgets={option?.widgets}\n onRemove={() => handleRemove(value)}\n />\n );\n })}\n </ul>\n </SortableContext>\n </DndContext>\n )}\n {!atMax && (\n <AddProviderControl\n options={options}\n excluded={selected}\n onAdd={handleAdd}\n ariaInvalid={!!field.error}\n />\n )}\n </div>\n );\n}\n\nfunction ProviderRow({\n value,\n index,\n label,\n widgets,\n onRemove,\n}: {\n value: string;\n index: number;\n label: string;\n widgets?: WidgetsByKind;\n onRemove: () => void;\n}) {\n const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({\n id: value,\n });\n const style: CSSProperties = {\n transform: transform\n ? `translate3d(${Math.round(transform.x)}px, ${Math.round(transform.y)}px, 0)`\n : undefined,\n transition,\n opacity: isDragging ? 0.6 : 1,\n };\n\n const { leading, pricing } = splitWidgets(widgets);\n const orderLabel = String(index + 1).padStart(2, \"0\");\n\n return (\n <li\n ref={setNodeRef}\n style={style}\n className={cn(\n \"pz:group/prov pz:flex pz:items-center pz:gap-2.5 pz:rounded-md pz:px-1.5 pz:py-1.5\",\n \"pz:hover:bg-muted/60 pz:transition-colors\",\n )}\n {...attributes}\n >\n <button\n type=\"button\"\n aria-label=\"Drag to reorder\"\n className={cn(\n \"pz:flex pz:items-center pz:justify-center pz:size-4 pz:cursor-grab pz:touch-none\",\n \"pz:text-muted-foreground/60 pz:hover:text-foreground pz:transition-colors\",\n )}\n {...listeners}\n >\n <IconGripVertical width={11} height={14} />\n </button>\n {leading && (\n <span className=\"pz:flex pz:items-center pz:shrink-0\">\n <WidgetStrip widgets={leading} size={18} />\n </span>\n )}\n <span className=\"pz:text-sm pz:font-medium pz:text-foreground pz:flex-1 pz:truncate\">\n {label}\n </span>\n {pricing && (\n <span className=\"pz:text-xs pz:text-muted-foreground pz:tabular-nums\">\n {pricing.credits} cr\n </span>\n )}\n <span\n aria-hidden\n className={cn(\n \"pz:inline-flex pz:items-center pz:justify-center pz:min-w-7 pz:h-5 pz:px-1.5\",\n \"pz:rounded-full pz:bg-muted pz:text-muted-foreground pz:text-[10.5px]\",\n \"pz:font-medium pz:tabular-nums\",\n )}\n >\n {orderLabel}\n </span>\n <button\n type=\"button\"\n aria-label={`Remove ${label}`}\n onClick={(e) => {\n e.stopPropagation();\n onRemove();\n }}\n className={cn(\n \"pz:flex pz:items-center pz:justify-center pz:size-5 pz:rounded\",\n \"pz:text-muted-foreground/70\",\n \"pz:hover:bg-destructive/10 pz:hover:text-destructive pz:transition-colors\",\n )}\n >\n <XIcon className=\"pz:size-3\" />\n </button>\n </li>\n );\n}\n\nfunction AddProviderControl({\n options,\n excluded,\n onAdd,\n ariaInvalid,\n}: {\n options: ProviderOption[];\n excluded: string[];\n onAdd: (value: string) => void;\n ariaInvalid?: boolean;\n}) {\n const [open, setOpen] = useState(false);\n const [query, setQuery] = useState(\"\");\n\n const excludedSet = useMemo(() => new Set(excluded), [excluded]);\n const available = useMemo(\n () => options.filter((o) => !excludedSet.has(o.value)),\n [options, excludedSet],\n );\n\n const filtered = useMemo(() => {\n const q = query.trim().toLowerCase();\n if (!q) return available;\n return available.filter(\n (o) => o.label.toLowerCase().includes(q) || o.value.toLowerCase().includes(q),\n );\n }, [available, query]);\n\n if (available.length === 0 && excluded.length === 0) {\n return (\n <div className=\"pz:text-xs pz:text-muted-foreground pz:px-1.5 pz:py-2\">\n No providers available\n </div>\n );\n }\n\n if (available.length === 0) return null;\n\n return (\n <Popover\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n if (!next) setQuery(\"\");\n }}\n >\n <PopoverTrigger\n aria-invalid={ariaInvalid || undefined}\n className={cn(\n \"pz:flex pz:items-center pz:justify-center pz:gap-1.5 pz:w-full\",\n \"pz:px-2.5 pz:py-1.5 pz:mt-1 pz:rounded-md\",\n \"pz:border pz:border-dashed pz:border-input pz:bg-transparent\",\n \"pz:text-xs pz:text-muted-foreground\",\n \"pz:hover:bg-muted/60 pz:hover:text-foreground pz:hover:border-muted-foreground/40\",\n \"pz:transition-colors pz:cursor-pointer\",\n )}\n >\n <IconPlus width={12} height={12} />\n Add provider\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"pz:w-(--anchor-width) pz:p-0 pz:gap-0\">\n <div className=\"pz:flex pz:items-center pz:gap-1.5 pz:px-2.5 pz:py-2 pz:border-b pz:border-border\">\n <SearchIcon className=\"pz:size-3.5 pz:text-muted-foreground pz:shrink-0\" />\n <input\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder=\"Search providers…\"\n // biome-ignore lint/a11y/noAutofocus: popover-scoped picker\n autoFocus\n className=\"pz:flex-1 pz:bg-transparent pz:outline-none pz:text-sm pz:placeholder:text-muted-foreground/70\"\n />\n </div>\n <ul className=\"pz:flex pz:flex-col pz:p-1 pz:max-h-72 pz:overflow-auto pz:list-none pz:m-0\">\n {filtered.length === 0 && (\n <li className=\"pz:px-2 pz:py-3 pz:text-center pz:text-xs pz:text-muted-foreground\">\n No providers\n </li>\n )}\n {filtered.map((option) => {\n const { leading, pricing } = splitWidgets(option.widgets);\n return (\n <li key={option.value} className=\"pz:contents\">\n <button\n type=\"button\"\n onClick={() => {\n onAdd(option.value);\n setOpen(false);\n setQuery(\"\");\n }}\n className={cn(\n \"pz:flex pz:items-center pz:gap-2 pz:w-full pz:text-left\",\n \"pz:px-2 pz:py-1.5 pz:rounded-md pz:text-sm\",\n \"pz:hover:bg-accent pz:hover:text-accent-foreground\",\n \"pz:transition-colors pz:cursor-pointer\",\n )}\n >\n {leading && (\n <span className=\"pz:flex pz:items-center pz:shrink-0\">\n <WidgetStrip widgets={leading} size={16} />\n </span>\n )}\n <span className=\"pz:flex-1 pz:truncate\">{option.label}</span>\n {pricing && (\n <span className=\"pz:text-xs pz:text-muted-foreground pz:tabular-nums\">\n {pricing.credits} cr\n </span>\n )}\n </button>\n </li>\n );\n })}\n </ul>\n </PopoverContent>\n </Popover>\n );\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"providers-input.mjs","names":["XIcon","SearchIcon"],"sources":["../../../../src/components/defaults/adapters/providers-input.tsx"],"sourcesContent":["import {\n closestCenter,\n DndContext,\n type DragEndEvent,\n KeyboardSensor,\n PointerSensor,\n useSensor,\n useSensors,\n} from \"@dnd-kit/core\";\nimport { SortableContext, useSortable, verticalListSortingStrategy } from \"@dnd-kit/sortable\";\nimport type { ProviderName, WidgetsByKind } from \"@pipe0/base\";\nimport { Search as SearchIcon, X as XIcon } from \"lucide-react\";\nimport { type CSSProperties, useMemo, useState } from \"react\";\nimport { cn } from \"../../../lib/utils.js\";\nimport type { FieldHandle } from \"../../../types/field-handle.js\";\nimport { AvatarGroup } from \"../../../widgets/avatar-group.js\";\nimport { PricingBadge } from \"../../../widgets/pricing-badge.js\";\nimport { WidgetStrip } from \"../../../widgets/widget-strip.js\";\nimport { IconGripVertical, IconPlus } from \"../../internal/icons.js\";\nimport { Popover, PopoverContent, PopoverTrigger } from \"../../ui/popover.js\";\n\ntype ProviderOption = {\n value: string;\n label: string;\n widgets?: WidgetsByKind;\n};\n\nfunction splitWidgets(widgets: WidgetsByKind | undefined): {\n providerName: ProviderName | undefined;\n leading: WidgetsByKind | undefined;\n pricing: WidgetsByKind[\"pricing\"] | undefined;\n} {\n if (!widgets) return { providerName: undefined, leading: undefined, pricing: undefined };\n const { pricing, provider_logo, ...rest } = widgets;\n const hasLeading = Object.values(rest).some((v) => v != null);\n return {\n providerName: provider_logo?.provider,\n leading: hasLeading ? rest : undefined,\n pricing,\n };\n}\n\nfunction LeadingAvatar({\n providerName,\n leading,\n}: {\n providerName: ProviderName | undefined;\n leading: WidgetsByKind | undefined;\n}) {\n if (providerName) {\n return <AvatarGroup providers={[providerName]} size=\"sm\" className=\"pz:shrink-0\" />;\n }\n if (leading) {\n return (\n <span className=\"pz:flex pz:items-center pz:shrink-0\">\n <WidgetStrip widgets={leading} size={18} />\n </span>\n );\n }\n return null;\n}\n\n/**\n * Provider waterfall — vertical, ordered list of providers tried sequentially\n * until a valid result is returned. The list makes the running order legible\n * (numeric badge per row, drag-to-reorder), and the credit widget per\n * provider stays visible.\n */\nexport function ProvidersInputAdapter(field: FieldHandle<\"providers_input\">) {\n const selected: string[] = useMemo(\n () => (field.value ?? []).map((p: { provider: string }) => p.provider),\n [field.value],\n );\n\n const options = field.options ?? [];\n const optionByValue = useMemo(() => {\n const map = new Map<string, ProviderOption>();\n for (const o of options) map.set(o.value, o);\n return map;\n }, [options]);\n\n const maxItems = field.meta.maxItems;\n const atMax = maxItems !== undefined && selected.length >= maxItems;\n\n const setValue = (next: string[]) =>\n field.setValue(next.map((provider) => ({ provider })));\n\n const handleRemove = (value: string) => setValue(selected.filter((v) => v !== value));\n const handleAdd = (value: string) => {\n if (selected.includes(value)) return;\n setValue([...selected, value]);\n };\n\n const sensors = useSensors(\n useSensor(PointerSensor, { activationConstraint: { distance: 4 } }),\n useSensor(KeyboardSensor),\n );\n\n const handleDragEnd = (event: DragEndEvent) => {\n const { active, over } = event;\n if (!over || active.id === over.id) return;\n const from = selected.indexOf(String(active.id));\n const to = selected.indexOf(String(over.id));\n if (from === -1 || to === -1) return;\n const next = [...selected];\n const [moved] = next.splice(from, 1);\n next.splice(to, 0, moved);\n setValue(next);\n };\n\n return (\n <div data-p0=\"input\" className=\"pz:flex pz:flex-col pz:gap-1\">\n {selected.length > 0 && (\n <DndContext\n sensors={sensors}\n collisionDetection={closestCenter}\n onDragEnd={handleDragEnd}\n >\n <SortableContext items={selected} strategy={verticalListSortingStrategy}>\n <ul className=\"pz:flex pz:flex-col pz:gap-0.5 pz:list-none pz:m-0 pz:p-0\">\n {selected.map((value, index) => {\n const option = optionByValue.get(value);\n return (\n <ProviderRow\n key={value}\n value={value}\n index={index}\n label={option?.label ?? value}\n widgets={option?.widgets}\n onRemove={() => handleRemove(value)}\n />\n );\n })}\n </ul>\n </SortableContext>\n </DndContext>\n )}\n {!atMax && (\n <AddProviderControl\n options={options}\n excluded={selected}\n onAdd={handleAdd}\n ariaInvalid={!!field.error}\n />\n )}\n </div>\n );\n}\n\nfunction ProviderRow({\n value,\n index,\n label,\n widgets,\n onRemove,\n}: {\n value: string;\n index: number;\n label: string;\n widgets?: WidgetsByKind;\n onRemove: () => void;\n}) {\n const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({\n id: value,\n });\n const style: CSSProperties = {\n transform: transform\n ? `translate3d(${Math.round(transform.x)}px, ${Math.round(transform.y)}px, 0)`\n : undefined,\n transition,\n opacity: isDragging ? 0.6 : 1,\n };\n\n const { providerName, leading, pricing } = splitWidgets(widgets);\n const orderLabel = String(index + 1).padStart(2, \"0\");\n\n return (\n <li\n ref={setNodeRef}\n style={style}\n className={cn(\n \"pz:group/prov pz:flex pz:items-center pz:gap-2.5 pz:rounded-md pz:px-1.5 pz:py-1.5\",\n \"pz:hover:bg-muted/60 pz:transition-colors\",\n )}\n {...attributes}\n >\n <button\n type=\"button\"\n aria-label=\"Drag to reorder\"\n className={cn(\n \"pz:flex pz:items-center pz:justify-center pz:size-4 pz:cursor-grab pz:touch-none\",\n \"pz:text-muted-foreground/60 pz:hover:text-foreground pz:transition-colors\",\n )}\n {...listeners}\n >\n <IconGripVertical width={11} height={14} />\n </button>\n <LeadingAvatar providerName={providerName} leading={leading} />\n <span className=\"pz:text-sm pz:font-medium pz:text-foreground pz:flex-1 pz:truncate\">\n {label}\n </span>\n {pricing && <PricingBadge credits={pricing.credits} />}\n <span\n aria-hidden\n className={cn(\n \"pz:inline-flex pz:items-center pz:justify-center pz:min-w-7 pz:h-5 pz:px-1.5\",\n \"pz:rounded-full pz:bg-muted pz:text-muted-foreground pz:text-[10.5px]\",\n \"pz:font-medium pz:tabular-nums\",\n )}\n >\n {orderLabel}\n </span>\n <button\n type=\"button\"\n aria-label={`Remove ${label}`}\n onClick={(e) => {\n e.stopPropagation();\n onRemove();\n }}\n className={cn(\n \"pz:flex pz:items-center pz:justify-center pz:size-5 pz:rounded\",\n \"pz:text-muted-foreground/70\",\n \"pz:hover:bg-destructive/10 pz:hover:text-destructive pz:transition-colors\",\n )}\n >\n <XIcon className=\"pz:size-3\" />\n </button>\n </li>\n );\n}\n\nfunction AddProviderControl({\n options,\n excluded,\n onAdd,\n ariaInvalid,\n}: {\n options: ProviderOption[];\n excluded: string[];\n onAdd: (value: string) => void;\n ariaInvalid?: boolean;\n}) {\n const [open, setOpen] = useState(false);\n const [query, setQuery] = useState(\"\");\n\n const excludedSet = useMemo(() => new Set(excluded), [excluded]);\n const available = useMemo(\n () => options.filter((o) => !excludedSet.has(o.value)),\n [options, excludedSet],\n );\n\n const filtered = useMemo(() => {\n const q = query.trim().toLowerCase();\n if (!q) return available;\n return available.filter(\n (o) => o.label.toLowerCase().includes(q) || o.value.toLowerCase().includes(q),\n );\n }, [available, query]);\n\n if (available.length === 0 && excluded.length === 0) {\n return (\n <div className=\"pz:text-xs pz:text-muted-foreground pz:px-1.5 pz:py-2\">\n No providers available\n </div>\n );\n }\n\n if (available.length === 0) return null;\n\n return (\n <Popover\n open={open}\n onOpenChange={(next) => {\n setOpen(next);\n if (!next) setQuery(\"\");\n }}\n >\n <PopoverTrigger\n aria-invalid={ariaInvalid || undefined}\n className={cn(\n \"pz:flex pz:items-center pz:justify-center pz:gap-1.5 pz:w-full\",\n \"pz:px-2.5 pz:py-1.5 pz:mt-1 pz:rounded-md\",\n \"pz:border pz:border-dashed pz:border-input pz:bg-transparent\",\n \"pz:text-xs pz:text-muted-foreground\",\n \"pz:hover:bg-muted/60 pz:hover:text-foreground pz:hover:border-muted-foreground/40\",\n \"pz:transition-colors pz:cursor-pointer\",\n )}\n >\n <IconPlus width={12} height={12} />\n Add provider\n </PopoverTrigger>\n <PopoverContent align=\"start\" className=\"pz:w-(--anchor-width) pz:p-0 pz:gap-0\">\n <div className=\"pz:flex pz:items-center pz:gap-1.5 pz:px-2.5 pz:py-2 pz:border-b pz:border-border\">\n <SearchIcon className=\"pz:size-3.5 pz:text-muted-foreground pz:shrink-0\" />\n <input\n value={query}\n onChange={(e) => setQuery(e.target.value)}\n placeholder=\"Search providers…\"\n // biome-ignore lint/a11y/noAutofocus: popover-scoped picker\n autoFocus\n className=\"pz:flex-1 pz:bg-transparent pz:outline-none pz:text-sm pz:placeholder:text-muted-foreground/70\"\n />\n </div>\n <ul className=\"pz:flex pz:flex-col pz:p-1 pz:max-h-72 pz:overflow-auto pz:list-none pz:m-0\">\n {filtered.length === 0 && (\n <li className=\"pz:px-2 pz:py-3 pz:text-center pz:text-xs pz:text-muted-foreground\">\n No providers\n </li>\n )}\n {filtered.map((option) => {\n const { providerName, leading, pricing } = splitWidgets(option.widgets);\n return (\n <li key={option.value} className=\"pz:contents\">\n <button\n type=\"button\"\n onClick={() => {\n onAdd(option.value);\n setOpen(false);\n setQuery(\"\");\n }}\n className={cn(\n \"pz:flex pz:items-center pz:gap-2 pz:w-full pz:text-left\",\n \"pz:px-2 pz:py-1.5 pz:rounded-md pz:text-sm\",\n \"pz:hover:bg-accent pz:hover:text-accent-foreground\",\n \"pz:transition-colors pz:cursor-pointer\",\n )}\n >\n <LeadingAvatar providerName={providerName} leading={leading} />\n <span className=\"pz:flex-1 pz:truncate\">{option.label}</span>\n {pricing && <PricingBadge credits={pricing.credits} />}\n </button>\n </li>\n );\n })}\n </ul>\n </PopoverContent>\n </Popover>\n );\n}\n"],"mappings":"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"}
@@ -27,7 +27,7 @@ function DefaultCatalogRoot({ className, render, children, ...props }) {
27
27
  render,
28
28
  ref: portalRef,
29
29
  props: mergeProps({
30
- className: cn("pz:flex pz:flex-col pz:gap-4", classNames?.root, className),
30
+ className: cn("pz:flex pz:flex-col pz:gap-1", classNames?.root, className),
31
31
  children: wrappedChildren,
32
32
  "data-p0": "catalog"
33
33
  }, props)
@@ -1 +1 @@
1
- {"version":3,"file":"layout.mjs","names":[],"sources":["../../../../src/components/defaults/catalog/layout.tsx"],"sourcesContent":["import { mergeProps } from \"@base-ui/react/merge-props\";\nimport { useRender } from \"@base-ui/react/use-render\";\nimport { type ReactNode, useCallback, useState } from \"react\";\nimport { useCatalogConfig } from \"../../../context/catalog-config-context.js\";\nimport { PortalContainerContext } from \"../../../context/portal-container-context.js\";\nimport { cn } from \"../../../lib/utils.js\";\n\n/**\n * Outermost catalog wrapper. Owns the `PortalContainerContext.Provider` so\n * elements-react popovers/dropdowns mounted inside the catalog tree portal\n * back into this container — keeping them inside the catalog's CSS scope.\n */\nexport function DefaultCatalogRoot({\n className,\n render,\n children,\n ...props\n}: useRender.ComponentProps<\"div\">) {\n const { classNames } = useCatalogConfig();\n const [portalContainer, setPortalContainer] = useState<HTMLElement | null>(null);\n const portalRef = useCallback((node: HTMLElement | null) => {\n setPortalContainer(node);\n }, []);\n\n const wrappedChildren: ReactNode = (\n <PortalContainerContext.Provider value={portalContainer}>\n {children}\n </PortalContainerContext.Provider>\n );\n\n return useRender({\n defaultTagName: \"div\",\n render,\n ref: portalRef,\n props: mergeProps<\"div\">(\n {\n className: cn(\"pz:flex pz:flex-col pz:gap-4\", classNames?.root, className),\n children: wrappedChildren,\n ...({ \"data-p0\": \"catalog\" } as Record<string, string>),\n },\n props,\n ),\n });\n}\n\nexport function DefaultCatalogList({\n className,\n render,\n ...props\n}: useRender.ComponentProps<\"div\">) {\n const { classNames } = useCatalogConfig();\n return useRender({\n defaultTagName: \"div\",\n render,\n props: mergeProps<\"div\">(\n {\n className: cn(\n \"pz:grid pz:gap-3 pz:grid-cols-1 pz:sm:grid-cols-2 pz:lg:grid-cols-3\",\n classNames?.list,\n className,\n ),\n ...({ \"data-p0\": \"catalog-list\" } as Record<string, string>),\n },\n props,\n ),\n });\n}\n\nexport function DefaultCatalogFilters({\n className,\n render,\n ...props\n}: useRender.ComponentProps<\"div\">) {\n const { classNames } = useCatalogConfig();\n return useRender({\n defaultTagName: \"div\",\n render,\n props: mergeProps<\"div\">(\n {\n className: cn(\"pz:flex pz:flex-wrap pz:gap-2\", classNames?.filters, className),\n ...({ \"data-p0\": \"catalog-filters\" } as Record<string, string>),\n },\n props,\n ),\n });\n}\n"],"mappings":";;;;;;;;;;;;;;AAYA,SAAgB,mBAAmB,EACjC,WACA,QACA,UACA,GAAG,SAC+B;CAClC,MAAM,EAAE,eAAe,kBAAkB;CACzC,MAAM,CAAC,iBAAiB,sBAAsB,SAA6B,KAAK;CAChF,MAAM,YAAY,aAAa,SAA6B;AAC1D,qBAAmB,KAAK;IACvB,EAAE,CAAC;CAEN,MAAM,kBACJ,oBAAC,uBAAuB,UAAxB;EAAiC,OAAO;EACrC;EAC+B;AAGpC,QAAO,UAAU;EACf,gBAAgB;EAChB;EACA,KAAK;EACL,OAAO,WACL;GACE,WAAW,GAAG,gCAAgC,YAAY,MAAM,UAAU;GAC1E,UAAU;GACJ,WAAW;GAClB,EACD,MACD;EACF,CAAC;;AA0BJ,SAAgB,sBAAsB,EACpC,WACA,QACA,GAAG,SAC+B;CAClC,MAAM,EAAE,eAAe,kBAAkB;AACzC,QAAO,UAAU;EACf,gBAAgB;EAChB;EACA,OAAO,WACL;GACE,WAAW,GAAG,iCAAiC,YAAY,SAAS,UAAU;GACxE,WAAW;GAClB,EACD,MACD;EACF,CAAC"}
1
+ {"version":3,"file":"layout.mjs","names":[],"sources":["../../../../src/components/defaults/catalog/layout.tsx"],"sourcesContent":["import { mergeProps } from \"@base-ui/react/merge-props\";\nimport { useRender } from \"@base-ui/react/use-render\";\nimport { type ReactNode, useCallback, useState } from \"react\";\nimport { useCatalogConfig } from \"../../../context/catalog-config-context.js\";\nimport { PortalContainerContext } from \"../../../context/portal-container-context.js\";\nimport { cn } from \"../../../lib/utils.js\";\n\n/**\n * Outermost catalog wrapper. Owns the `PortalContainerContext.Provider` so\n * elements-react popovers/dropdowns mounted inside the catalog tree portal\n * back into this container — keeping them inside the catalog's CSS scope.\n */\nexport function DefaultCatalogRoot({\n className,\n render,\n children,\n ...props\n}: useRender.ComponentProps<\"div\">) {\n const { classNames } = useCatalogConfig();\n const [portalContainer, setPortalContainer] = useState<HTMLElement | null>(null);\n const portalRef = useCallback((node: HTMLElement | null) => {\n setPortalContainer(node);\n }, []);\n\n const wrappedChildren: ReactNode = (\n <PortalContainerContext.Provider value={portalContainer}>\n {children}\n </PortalContainerContext.Provider>\n );\n\n return useRender({\n defaultTagName: \"div\",\n render,\n ref: portalRef,\n props: mergeProps<\"div\">(\n {\n className: cn(\"pz:flex pz:flex-col pz:gap-1\", classNames?.root, className),\n children: wrappedChildren,\n ...({ \"data-p0\": \"catalog\" } as Record<string, string>),\n },\n props,\n ),\n });\n}\n\nexport function DefaultCatalogList({\n className,\n render,\n ...props\n}: useRender.ComponentProps<\"div\">) {\n const { classNames } = useCatalogConfig();\n return useRender({\n defaultTagName: \"div\",\n render,\n props: mergeProps<\"div\">(\n {\n className: cn(\n \"pz:grid pz:gap-3 pz:grid-cols-1 pz:sm:grid-cols-2 pz:lg:grid-cols-3\",\n classNames?.list,\n className,\n ),\n ...({ \"data-p0\": \"catalog-list\" } as Record<string, string>),\n },\n props,\n ),\n });\n}\n\nexport function DefaultCatalogFilters({\n className,\n render,\n ...props\n}: useRender.ComponentProps<\"div\">) {\n const { classNames } = useCatalogConfig();\n return useRender({\n defaultTagName: \"div\",\n render,\n props: mergeProps<\"div\">(\n {\n className: cn(\"pz:flex pz:flex-wrap pz:gap-2\", classNames?.filters, className),\n ...({ \"data-p0\": \"catalog-filters\" } as Record<string, string>),\n },\n props,\n ),\n });\n}\n"],"mappings":";;;;;;;;;;;;;;AAYA,SAAgB,mBAAmB,EACjC,WACA,QACA,UACA,GAAG,SAC+B;CAClC,MAAM,EAAE,eAAe,kBAAkB;CACzC,MAAM,CAAC,iBAAiB,sBAAsB,SAA6B,KAAK;CAChF,MAAM,YAAY,aAAa,SAA6B;AAC1D,qBAAmB,KAAK;IACvB,EAAE,CAAC;CAEN,MAAM,kBACJ,oBAAC,uBAAuB,UAAxB;EAAiC,OAAO;EACrC;EAC+B;AAGpC,QAAO,UAAU;EACf,gBAAgB;EAChB;EACA,KAAK;EACL,OAAO,WACL;GACE,WAAW,GAAG,gCAAgC,YAAY,MAAM,UAAU;GAC1E,UAAU;GACJ,WAAW;GAClB,EACD,MACD;EACF,CAAC;;AA0BJ,SAAgB,sBAAsB,EACpC,WACA,QACA,GAAG,SAC+B;CAClC,MAAM,EAAE,eAAe,kBAAkB;AACzC,QAAO,UAAU;EACf,gBAAgB;EAChB;EACA,OAAO,WACL;GACE,WAAW,GAAG,iCAAiC,YAAY,SAAS,UAAU;GACxE,WAAW;GAClB,EACD,MACD;EACF,CAAC"}
@@ -16,7 +16,8 @@ function DefaultGroup({ group, children, className, render, ...props }) {
16
16
  const { classNames } = useFormConfig();
17
17
  const [expanded, setExpanded] = useState(group.defaultExpand);
18
18
  const hasErrors = group.errorCount > 0;
19
- const countLabel = group.dirtyCount > 0 ? `${group.dirtyCount} modified` : group.setCount > 0 ? `${group.setCount} set` : null;
19
+ const showDirty = group.dirtyCount > 0;
20
+ const countLabel = showDirty ? `${group.dirtyCount} modified` : group.setCount > 0 ? `${group.setCount} set` : null;
20
21
  const defaultContent = /* @__PURE__ */ jsx(Accordion.Root, {
21
22
  value: expanded ? [ITEM_VALUE] : [],
22
23
  onValueChange: (next) => setExpanded(next.includes(ITEM_VALUE)),
@@ -46,7 +47,7 @@ function DefaultGroup({ group, children, className, render, ...props }) {
46
47
  className: "pz:flex pz:items-center pz:gap-2",
47
48
  children: [
48
49
  countLabel && /* @__PURE__ */ jsx(Badge, {
49
- variant: "secondary",
50
+ variant: showDirty ? "default" : "secondary",
50
51
  "data-p0": "group-badge",
51
52
  children: countLabel
52
53
  }),
@@ -71,7 +72,7 @@ function DefaultGroup({ group, children, className, render, ...props }) {
71
72
  "data-p0": "group-content",
72
73
  className: "pz:overflow-hidden pz:border-t pz:border-border pz:data-open:animate-accordion-down pz:data-closed:animate-accordion-up",
73
74
  children: /* @__PURE__ */ jsx("div", {
74
- className: classNames?.groupContent ?? cn("pz:flex pz:flex-col pz:gap-3 pz:px-3.5 pz:pb-3.5 pz:pt-2", "pz:h-(--accordion-panel-height) pz:data-ending-style:h-0 pz:data-starting-style:h-0"),
75
+ className: classNames?.groupContent ?? cn("pz:flex pz:flex-col pz:gap-3 pz:px-3.5 pz:pb-2 pz:pt-2", "pz:h-(--accordion-panel-height) pz:data-ending-style:h-0 pz:data-starting-style:h-0"),
75
76
  children
76
77
  })
77
78
  })]
@@ -1 +1 @@
1
- {"version":3,"file":"group.mjs","names":["AccordionPrimitive"],"sources":["../../../../src/components/defaults/layout/group.tsx"],"sourcesContent":["import { Accordion as AccordionPrimitive } from \"@base-ui/react/accordion\";\nimport { mergeProps } from \"@base-ui/react/merge-props\";\nimport { useRender } from \"@base-ui/react/use-render\";\nimport { useState } from \"react\";\nimport { useFormConfig } from \"../../../context/form-context.js\";\nimport { cn } from \"../../../lib/utils.js\";\nimport type { AnyFieldProps } from \"../../../types/field-props.js\";\nimport type { FormGroupHandle } from \"../../../types/form-handle.js\";\nimport { IconGlyph } from \"../../../widgets/icon-glyph.js\";\nimport { HoverInfo } from \"../../hover-info.js\";\nimport { IconChevronDown } from \"../../internal/icons.js\";\nimport { Badge } from \"../../ui/badge.js\";\n\nexport interface DefaultGroupState {\n expanded: boolean;\n setExpanded: (expanded: boolean) => void;\n fields: ReadonlyArray<AnyFieldProps>;\n hasErrors: boolean;\n errorCount: number;\n setCount: number;\n dirtyCount: number;\n}\n\nexport interface DefaultGroupProps extends useRender.ComponentProps<\"div\", DefaultGroupState> {\n group: FormGroupHandle;\n}\n\nconst ITEM_VALUE = \"group\";\n\nexport function DefaultGroup({ group, children, className, render, ...props }: DefaultGroupProps) {\n const { classNames } = useFormConfig();\n // Track open state alongside the accordion so consumers reading\n // `state.expanded` (via render-prop) still get the right value.\n const [expanded, setExpanded] = useState(group.defaultExpand);\n const hasErrors = group.errorCount > 0;\n const showDirty = group.dirtyCount > 0;\n const countLabel = showDirty\n ? `${group.dirtyCount} modified`\n : group.setCount > 0\n ? `${group.setCount} set`\n : null;\n\n const defaultContent = (\n <AccordionPrimitive.Root\n value={expanded ? [ITEM_VALUE] : []}\n onValueChange={(next) => setExpanded(next.includes(ITEM_VALUE))}\n >\n <AccordionPrimitive.Item value={ITEM_VALUE}>\n <AccordionPrimitive.Header className=\"pz:flex\">\n <AccordionPrimitive.Trigger\n data-p0=\"group-header\"\n className={\n classNames?.groupHeader ??\n cn(\n \"pz:group/group-trigger\",\n \"pz:flex pz:items-center pz:justify-between pz:gap-4 pz:w-full\",\n \"pz:px-3.5 pz:py-2.5 pz:cursor-pointer pz:text-sm pz:font-medium pz:text-left\",\n \"pz:transition-colors pz:hover:bg-muted/60\",\n \"pz:aria-expanded:hover:bg-transparent\",\n \"pz:focus-visible:outline-none\",\n hasErrors && \"pz:text-destructive pz:bg-destructive/10\",\n )\n }\n >\n <span className=\"pz:flex pz:items-center pz:gap-2\">\n {group.iconKey && (\n <IconGlyph\n keyName={group.iconKey}\n size={14}\n className=\"pz:text-muted-foreground pz:shrink-0\"\n />\n )}\n {group.label ?? group.key}\n {group.description && (\n <span onClick={(e) => e.stopPropagation()} onKeyDown={(e) => e.stopPropagation()}>\n <HoverInfo>{group.description}</HoverInfo>\n </span>\n )}\n </span>\n <span className=\"pz:flex pz:items-center pz:gap-2\">\n {countLabel && (\n <Badge variant=\"secondary\" data-p0=\"group-badge\">\n {countLabel}\n </Badge>\n )}\n {hasErrors && (\n <Badge variant=\"destructive\" data-p0=\"group-error-badge\">\n {group.errorCount} {group.errorCount === 1 ? \"error\" : \"errors\"}\n </Badge>\n )}\n <IconChevronDown\n width={16}\n height={16}\n className={cn(\n \"pz:text-muted-foreground pz:transition-transform pz:duration-150\",\n \"pz:group-aria-expanded/group-trigger:rotate-180\",\n )}\n />\n </span>\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n <AccordionPrimitive.Panel\n data-p0=\"group-content\"\n // The library ships keyframes via `tw-animate-css` —\n // `animate-accordion-down` / `animate-accordion-up` plus the\n // `--accordion-panel-height` var that base-ui populates on the\n // panel give a smooth height transition without JS measuring.\n className=\"pz:overflow-hidden pz:border-t pz:border-border pz:data-open:animate-accordion-down pz:data-closed:animate-accordion-up\"\n >\n <div\n className={\n classNames?.groupContent ??\n cn(\n \"pz:flex pz:flex-col pz:gap-3 pz:px-3.5 pz:pb-3.5 pz:pt-2\",\n \"pz:h-(--accordion-panel-height) pz:data-ending-style:h-0 pz:data-starting-style:h-0\",\n )\n }\n >\n {children}\n </div>\n </AccordionPrimitive.Panel>\n </AccordionPrimitive.Item>\n </AccordionPrimitive.Root>\n );\n\n return useRender({\n defaultTagName: \"div\",\n render,\n state: {\n expanded,\n setExpanded,\n fields: group.fields,\n hasErrors,\n errorCount: group.errorCount,\n setCount: group.setCount,\n dirtyCount: group.dirtyCount,\n },\n stateAttributesMapping: {\n setExpanded: () => null,\n fields: () => null,\n },\n props: mergeProps<\"div\">(\n {\n className: cn(\n classNames?.group ??\n cn(\n \"pz:flex pz:flex-col pz:bg-card pz:border pz:border-border pz:rounded-lg pz:overflow-hidden\",\n hasErrors && \"pz:border-destructive\",\n ),\n className,\n ),\n children: defaultContent,\n ...({\n \"data-p0\": \"group\",\n \"data-p0-group\": group.key,\n \"data-p0-expanded\": String(expanded),\n } as Record<string, string>),\n },\n props,\n ),\n });\n}\n"],"mappings":";;;;;;;;;;;;;AA2BA,MAAM,aAAa;AAEnB,SAAgB,aAAa,EAAE,OAAO,UAAU,WAAW,QAAQ,GAAG,SAA4B;CAChG,MAAM,EAAE,eAAe,eAAe;CAGtC,MAAM,CAAC,UAAU,eAAe,SAAS,MAAM,cAAc;CAC7D,MAAM,YAAY,MAAM,aAAa;CAErC,MAAM,aADY,MAAM,aAAa,IAEjC,GAAG,MAAM,WAAW,aACpB,MAAM,WAAW,IACf,GAAG,MAAM,SAAS,QAClB;CAEN,MAAM,iBACJ,oBAACA,UAAmB,MAApB;EACE,OAAO,WAAW,CAAC,WAAW,GAAG,EAAE;EACnC,gBAAgB,SAAS,YAAY,KAAK,SAAS,WAAW,CAAC;YAE/D,qBAACA,UAAmB,MAApB;GAAyB,OAAO;aAAhC,CACE,oBAACA,UAAmB,QAApB;IAA2B,WAAU;cACnC,qBAACA,UAAmB,SAApB;KACE,WAAQ;KACR,WACE,YAAY,eACZ,GACE,0BACA,iEACA,gFACA,6CACA,yCACA,iCACA,aAAa,2CACd;eAZL,CAeE,qBAAC,QAAD;MAAM,WAAU;gBAAhB;OACG,MAAM,WACL,oBAAC,WAAD;QACE,SAAS,MAAM;QACf,MAAM;QACN,WAAU;QACV;OAEH,MAAM,SAAS,MAAM;OACrB,MAAM,eACL,oBAAC,QAAD;QAAM,UAAU,MAAM,EAAE,iBAAiB;QAAE,YAAY,MAAM,EAAE,iBAAiB;kBAC9E,oBAAC,WAAD,YAAY,MAAM,aAAwB;QACrC;OAEJ;SACP,qBAAC,QAAD;MAAM,WAAU;gBAAhB;OACG,cACC,oBAAC,OAAD;QAAO,SAAQ;QAAY,WAAQ;kBAChC;QACK;OAET,aACC,qBAAC,OAAD;QAAO,SAAQ;QAAc,WAAQ;kBAArC;SACG,MAAM;SAAW;SAAE,MAAM,eAAe,IAAI,UAAU;SACjD;;OAEV,oBAAC,iBAAD;QACE,OAAO;QACP,QAAQ;QACR,WAAW,GACT,oEACA,kDACD;QACD;OACG;QACoB;;IACH,GAC5B,oBAACA,UAAmB,OAApB;IACE,WAAQ;IAKR,WAAU;cAEV,oBAAC,OAAD;KACE,WACE,YAAY,gBACZ,GACE,4DACA,sFACD;KAGF;KACG;IACmB,EACH;;EACF;AAG5B,QAAO,UAAU;EACf,gBAAgB;EAChB;EACA,OAAO;GACL;GACA;GACA,QAAQ,MAAM;GACd;GACA,YAAY,MAAM;GAClB,UAAU,MAAM;GAChB,YAAY,MAAM;GACnB;EACD,wBAAwB;GACtB,mBAAmB;GACnB,cAAc;GACf;EACD,OAAO,WACL;GACE,WAAW,GACT,YAAY,SACV,GACE,8FACA,aAAa,wBACd,EACH,UACD;GACD,UAAU;GAER,WAAW;GACX,iBAAiB,MAAM;GACvB,oBAAoB,OAAO,SAAS;GAEvC,EACD,MACD;EACF,CAAC"}
1
+ {"version":3,"file":"group.mjs","names":["AccordionPrimitive"],"sources":["../../../../src/components/defaults/layout/group.tsx"],"sourcesContent":["import { Accordion as AccordionPrimitive } from \"@base-ui/react/accordion\";\nimport { mergeProps } from \"@base-ui/react/merge-props\";\nimport { useRender } from \"@base-ui/react/use-render\";\nimport { useState } from \"react\";\nimport { useFormConfig } from \"../../../context/form-context.js\";\nimport { cn } from \"../../../lib/utils.js\";\nimport type { AnyFieldProps } from \"../../../types/field-props.js\";\nimport type { FormGroupHandle } from \"../../../types/form-handle.js\";\nimport { IconGlyph } from \"../../../widgets/icon-glyph.js\";\nimport { HoverInfo } from \"../../hover-info.js\";\nimport { IconChevronDown } from \"../../internal/icons.js\";\nimport { Badge } from \"../../ui/badge.js\";\n\nexport interface DefaultGroupState {\n expanded: boolean;\n setExpanded: (expanded: boolean) => void;\n fields: ReadonlyArray<AnyFieldProps>;\n hasErrors: boolean;\n errorCount: number;\n setCount: number;\n dirtyCount: number;\n}\n\nexport interface DefaultGroupProps extends useRender.ComponentProps<\"div\", DefaultGroupState> {\n group: FormGroupHandle;\n}\n\nconst ITEM_VALUE = \"group\";\n\nexport function DefaultGroup({ group, children, className, render, ...props }: DefaultGroupProps) {\n const { classNames } = useFormConfig();\n // Track open state alongside the accordion so consumers reading\n // `state.expanded` (via render-prop) still get the right value.\n const [expanded, setExpanded] = useState(group.defaultExpand);\n const hasErrors = group.errorCount > 0;\n const showDirty = group.dirtyCount > 0;\n const countLabel = showDirty\n ? `${group.dirtyCount} modified`\n : group.setCount > 0\n ? `${group.setCount} set`\n : null;\n\n const defaultContent = (\n <AccordionPrimitive.Root\n value={expanded ? [ITEM_VALUE] : []}\n onValueChange={(next) => setExpanded(next.includes(ITEM_VALUE))}\n >\n <AccordionPrimitive.Item value={ITEM_VALUE}>\n <AccordionPrimitive.Header className=\"pz:flex\">\n <AccordionPrimitive.Trigger\n data-p0=\"group-header\"\n className={\n classNames?.groupHeader ??\n cn(\n \"pz:group/group-trigger\",\n \"pz:flex pz:items-center pz:justify-between pz:gap-4 pz:w-full\",\n \"pz:px-3.5 pz:py-2.5 pz:cursor-pointer pz:text-sm pz:font-medium pz:text-left\",\n \"pz:transition-colors pz:hover:bg-muted/60\",\n \"pz:aria-expanded:hover:bg-transparent\",\n \"pz:focus-visible:outline-none\",\n hasErrors && \"pz:text-destructive pz:bg-destructive/10\",\n )\n }\n >\n <span className=\"pz:flex pz:items-center pz:gap-2\">\n {group.iconKey && (\n <IconGlyph\n keyName={group.iconKey}\n size={14}\n className=\"pz:text-muted-foreground pz:shrink-0\"\n />\n )}\n {group.label ?? group.key}\n {group.description && (\n <span onClick={(e) => e.stopPropagation()} onKeyDown={(e) => e.stopPropagation()}>\n <HoverInfo>{group.description}</HoverInfo>\n </span>\n )}\n </span>\n <span className=\"pz:flex pz:items-center pz:gap-2\">\n {countLabel && (\n <Badge variant={showDirty ? \"default\" : \"secondary\"} data-p0=\"group-badge\">\n {countLabel}\n </Badge>\n )}\n {hasErrors && (\n <Badge variant=\"destructive\" data-p0=\"group-error-badge\">\n {group.errorCount} {group.errorCount === 1 ? \"error\" : \"errors\"}\n </Badge>\n )}\n <IconChevronDown\n width={16}\n height={16}\n className={cn(\n \"pz:text-muted-foreground pz:transition-transform pz:duration-150\",\n \"pz:group-aria-expanded/group-trigger:rotate-180\",\n )}\n />\n </span>\n </AccordionPrimitive.Trigger>\n </AccordionPrimitive.Header>\n <AccordionPrimitive.Panel\n data-p0=\"group-content\"\n // The library ships keyframes via `tw-animate-css` —\n // `animate-accordion-down` / `animate-accordion-up` plus the\n // `--accordion-panel-height` var that base-ui populates on the\n // panel give a smooth height transition without JS measuring.\n className=\"pz:overflow-hidden pz:border-t pz:border-border pz:data-open:animate-accordion-down pz:data-closed:animate-accordion-up\"\n >\n <div\n className={\n classNames?.groupContent ??\n cn(\n \"pz:flex pz:flex-col pz:gap-3 pz:px-3.5 pz:pb-2 pz:pt-2\",\n \"pz:h-(--accordion-panel-height) pz:data-ending-style:h-0 pz:data-starting-style:h-0\",\n )\n }\n >\n {children}\n </div>\n </AccordionPrimitive.Panel>\n </AccordionPrimitive.Item>\n </AccordionPrimitive.Root>\n );\n\n return useRender({\n defaultTagName: \"div\",\n render,\n state: {\n expanded,\n setExpanded,\n fields: group.fields,\n hasErrors,\n errorCount: group.errorCount,\n setCount: group.setCount,\n dirtyCount: group.dirtyCount,\n },\n stateAttributesMapping: {\n setExpanded: () => null,\n fields: () => null,\n },\n props: mergeProps<\"div\">(\n {\n className: cn(\n classNames?.group ??\n cn(\n \"pz:flex pz:flex-col pz:bg-card pz:border pz:border-border pz:rounded-lg pz:overflow-hidden\",\n hasErrors && \"pz:border-destructive\",\n ),\n className,\n ),\n children: defaultContent,\n ...({\n \"data-p0\": \"group\",\n \"data-p0-group\": group.key,\n \"data-p0-expanded\": String(expanded),\n } as Record<string, string>),\n },\n props,\n ),\n });\n}\n"],"mappings":";;;;;;;;;;;;;AA2BA,MAAM,aAAa;AAEnB,SAAgB,aAAa,EAAE,OAAO,UAAU,WAAW,QAAQ,GAAG,SAA4B;CAChG,MAAM,EAAE,eAAe,eAAe;CAGtC,MAAM,CAAC,UAAU,eAAe,SAAS,MAAM,cAAc;CAC7D,MAAM,YAAY,MAAM,aAAa;CACrC,MAAM,YAAY,MAAM,aAAa;CACrC,MAAM,aAAa,YACf,GAAG,MAAM,WAAW,aACpB,MAAM,WAAW,IACf,GAAG,MAAM,SAAS,QAClB;CAEN,MAAM,iBACJ,oBAACA,UAAmB,MAApB;EACE,OAAO,WAAW,CAAC,WAAW,GAAG,EAAE;EACnC,gBAAgB,SAAS,YAAY,KAAK,SAAS,WAAW,CAAC;YAE/D,qBAACA,UAAmB,MAApB;GAAyB,OAAO;aAAhC,CACE,oBAACA,UAAmB,QAApB;IAA2B,WAAU;cACnC,qBAACA,UAAmB,SAApB;KACE,WAAQ;KACR,WACE,YAAY,eACZ,GACE,0BACA,iEACA,gFACA,6CACA,yCACA,iCACA,aAAa,2CACd;eAZL,CAeE,qBAAC,QAAD;MAAM,WAAU;gBAAhB;OACG,MAAM,WACL,oBAAC,WAAD;QACE,SAAS,MAAM;QACf,MAAM;QACN,WAAU;QACV;OAEH,MAAM,SAAS,MAAM;OACrB,MAAM,eACL,oBAAC,QAAD;QAAM,UAAU,MAAM,EAAE,iBAAiB;QAAE,YAAY,MAAM,EAAE,iBAAiB;kBAC9E,oBAAC,WAAD,YAAY,MAAM,aAAwB;QACrC;OAEJ;SACP,qBAAC,QAAD;MAAM,WAAU;gBAAhB;OACG,cACC,oBAAC,OAAD;QAAO,SAAS,YAAY,YAAY;QAAa,WAAQ;kBAC1D;QACK;OAET,aACC,qBAAC,OAAD;QAAO,SAAQ;QAAc,WAAQ;kBAArC;SACG,MAAM;SAAW;SAAE,MAAM,eAAe,IAAI,UAAU;SACjD;;OAEV,oBAAC,iBAAD;QACE,OAAO;QACP,QAAQ;QACR,WAAW,GACT,oEACA,kDACD;QACD;OACG;QACoB;;IACH,GAC5B,oBAACA,UAAmB,OAApB;IACE,WAAQ;IAKR,WAAU;cAEV,oBAAC,OAAD;KACE,WACE,YAAY,gBACZ,GACE,0DACA,sFACD;KAGF;KACG;IACmB,EACH;;EACF;AAG5B,QAAO,UAAU;EACf,gBAAgB;EAChB;EACA,OAAO;GACL;GACA;GACA,QAAQ,MAAM;GACd;GACA,YAAY,MAAM;GAClB,UAAU,MAAM;GAChB,YAAY,MAAM;GACnB;EACD,wBAAwB;GACtB,mBAAmB;GACnB,cAAc;GACf;EACD,OAAO,WACL;GACE,WAAW,GACT,YAAY,SACV,GACE,8FACA,aAAa,wBACd,EACH,UACD;GACD,UAAU;GAER,WAAW;GACX,iBAAiB,MAAM;GACvB,oBAAoB,OAAO,SAAS;GAEvC,EACD,MACD;EACF,CAAC"}
@@ -10,7 +10,7 @@ function DefaultSection({ section, children, className, render, hideLabel, ...pr
10
10
  const hasErrors = section.groups.some((g) => g.errorCount > 0);
11
11
  const defaultContent = /* @__PURE__ */ jsxs(Fragment, { children: [!hideLabel && section.label && /* @__PURE__ */ jsxs("div", {
12
12
  "data-p0": "section-header",
13
- className: classNames?.sectionLabel ?? "pz:flex pz:items-center pz:gap-2.5 pz:px-1",
13
+ className: classNames?.sectionLabel ?? "pz:flex pz:items-center pz:gap-2.5 pz:px-1 mb-0.5 mt-2 pz:select-none",
14
14
  children: [/* @__PURE__ */ jsx("h2", {
15
15
  className: cn("pz:text-[10.5px] pz:font-medium pz:tracking-[0.12em] pz:uppercase pz:text-muted-foreground pz:m-0 pz:whitespace-nowrap"),
16
16
  children: section.label
@@ -1 +1 @@
1
- {"version":3,"file":"section.mjs","names":[],"sources":["../../../../src/components/defaults/layout/section.tsx"],"sourcesContent":["import { mergeProps } from \"@base-ui/react/merge-props\";\nimport { useRender } from \"@base-ui/react/use-render\";\nimport { useFormConfig } from \"../../../context/form-context.js\";\nimport { cn } from \"../../../lib/utils.js\";\nimport type { FormGroupHandle, FormSectionHandle } from \"../../../types/form-handle.js\";\n\nexport interface DefaultSectionState {\n groups: ReadonlyArray<FormGroupHandle>;\n hasErrors: boolean;\n}\n\nexport interface DefaultSectionProps extends useRender.ComponentProps<\"div\", DefaultSectionState> {\n section: FormSectionHandle;\n /**\n * Suppress the section's own header. Set when several consecutive sections\n * share an umbrella label so the label only renders above the first\n * section in the cluster (the renderer in `pipe-form/content.tsx` and\n * `search-form/content.tsx` handles this automatically).\n */\n hideLabel?: boolean;\n}\n\nexport function DefaultSection({\n section,\n children,\n className,\n render,\n hideLabel,\n ...props\n}: DefaultSectionProps) {\n const { classNames } = useFormConfig();\n const hasErrors = section.groups.some((g) => g.errorCount > 0);\n\n // Section descriptions are intentionally not rendered — the umbrella label\n // alone is enough signal, and per-section descriptions add noise once\n // multiple sections sit under one umbrella. Field-level descriptions cover\n // the cases where copy is actually load-bearing.\n const defaultContent = (\n <>\n {!hideLabel && section.label && (\n <div\n data-p0=\"section-header\"\n className={classNames?.sectionLabel ?? \"pz:flex pz:items-center pz:gap-2.5 pz:px-1\"}\n >\n <h2\n className={cn(\n \"pz:text-[10.5px] pz:font-medium pz:tracking-[0.12em] pz:uppercase pz:text-muted-foreground pz:m-0 pz:whitespace-nowrap\",\n )}\n >\n {section.label}\n </h2>\n <span aria-hidden className=\"pz:flex-1 pz:h-px pz:bg-border\" />\n </div>\n )}\n {children}\n </>\n );\n\n return useRender({\n defaultTagName: \"div\",\n render,\n state: { groups: section.groups, hasErrors },\n stateAttributesMapping: {\n groups: () => null,\n },\n props: mergeProps<\"div\">(\n {\n className: cn(classNames?.section ?? \"pz:flex pz:flex-col pz:gap-2\", className),\n children: defaultContent,\n ...({\n \"data-p0\": \"section\",\n \"data-p0-section\": section.key,\n } as Record<string, string>),\n },\n props,\n ),\n });\n}\n"],"mappings":";;;;;;;AAsBA,SAAgB,eAAe,EAC7B,SACA,UACA,WACA,QACA,WACA,GAAG,SACmB;CACtB,MAAM,EAAE,eAAe,eAAe;CACtC,MAAM,YAAY,QAAQ,OAAO,MAAM,MAAM,EAAE,aAAa,EAAE;CAM9D,MAAM,iBACJ,4CACG,CAAC,aAAa,QAAQ,SACrB,qBAAC,OAAD;EACE,WAAQ;EACR,WAAW,YAAY,gBAAgB;YAFzC,CAIE,oBAAC,MAAD;GACE,WAAW,GACT,yHACD;aAEA,QAAQ;GACN,GACL,oBAAC,QAAD;GAAM;GAAY,WAAU;GAAmC,EAC3D;KAEP,SACA;AAGL,QAAO,UAAU;EACf,gBAAgB;EAChB;EACA,OAAO;GAAE,QAAQ,QAAQ;GAAQ;GAAW;EAC5C,wBAAwB,EACtB,cAAc,MACf;EACD,OAAO,WACL;GACE,WAAW,GAAG,YAAY,WAAW,gCAAgC,UAAU;GAC/E,UAAU;GAER,WAAW;GACX,mBAAmB,QAAQ;GAE9B,EACD,MACD;EACF,CAAC"}
1
+ {"version":3,"file":"section.mjs","names":[],"sources":["../../../../src/components/defaults/layout/section.tsx"],"sourcesContent":["import { mergeProps } from \"@base-ui/react/merge-props\";\nimport { useRender } from \"@base-ui/react/use-render\";\nimport { useFormConfig } from \"../../../context/form-context.js\";\nimport { cn } from \"../../../lib/utils.js\";\nimport type { FormGroupHandle, FormSectionHandle } from \"../../../types/form-handle.js\";\n\nexport interface DefaultSectionState {\n groups: ReadonlyArray<FormGroupHandle>;\n hasErrors: boolean;\n}\n\nexport interface DefaultSectionProps extends useRender.ComponentProps<\"div\", DefaultSectionState> {\n section: FormSectionHandle;\n /**\n * Suppress the section's own header. Set when several consecutive sections\n * share an umbrella label so the label only renders above the first\n * section in the cluster (the renderer in `pipe-form/content.tsx` and\n * `search-form/content.tsx` handles this automatically).\n */\n hideLabel?: boolean;\n}\n\nexport function DefaultSection({\n section,\n children,\n className,\n render,\n hideLabel,\n ...props\n}: DefaultSectionProps) {\n const { classNames } = useFormConfig();\n const hasErrors = section.groups.some((g) => g.errorCount > 0);\n\n // Section descriptions are intentionally not rendered — the umbrella label\n // alone is enough signal, and per-section descriptions add noise once\n // multiple sections sit under one umbrella. Field-level descriptions cover\n // the cases where copy is actually load-bearing.\n const defaultContent = (\n <>\n {!hideLabel && section.label && (\n <div\n data-p0=\"section-header\"\n className={\n classNames?.sectionLabel ??\n \"pz:flex pz:items-center pz:gap-2.5 pz:px-1 mb-0.5 mt-2 pz:select-none\"\n }\n >\n <h2\n className={cn(\n \"pz:text-[10.5px] pz:font-medium pz:tracking-[0.12em] pz:uppercase pz:text-muted-foreground pz:m-0 pz:whitespace-nowrap\",\n )}\n >\n {section.label}\n </h2>\n <span aria-hidden className=\"pz:flex-1 pz:h-px pz:bg-border\" />\n </div>\n )}\n {children}\n </>\n );\n\n return useRender({\n defaultTagName: \"div\",\n render,\n state: { groups: section.groups, hasErrors },\n stateAttributesMapping: {\n groups: () => null,\n },\n props: mergeProps<\"div\">(\n {\n className: cn(classNames?.section ?? \"pz:flex pz:flex-col pz:gap-2\", className),\n children: defaultContent,\n ...({\n \"data-p0\": \"section\",\n \"data-p0-section\": section.key,\n } as Record<string, string>),\n },\n props,\n ),\n });\n}\n"],"mappings":";;;;;;;AAsBA,SAAgB,eAAe,EAC7B,SACA,UACA,WACA,QACA,WACA,GAAG,SACmB;CACtB,MAAM,EAAE,eAAe,eAAe;CACtC,MAAM,YAAY,QAAQ,OAAO,MAAM,MAAM,EAAE,aAAa,EAAE;CAM9D,MAAM,iBACJ,4CACG,CAAC,aAAa,QAAQ,SACrB,qBAAC,OAAD;EACE,WAAQ;EACR,WACE,YAAY,gBACZ;YAJJ,CAOE,oBAAC,MAAD;GACE,WAAW,GACT,yHACD;aAEA,QAAQ;GACN,GACL,oBAAC,QAAD;GAAM;GAAY,WAAU;GAAmC,EAC3D;KAEP,SACA;AAGL,QAAO,UAAU;EACf,gBAAgB;EAChB;EACA,OAAO;GAAE,QAAQ,QAAQ;GAAQ;GAAW;EAC5C,wBAAwB,EACtB,cAAc,MACf;EACD,OAAO,WACL;GACE,WAAW,GAAG,YAAY,WAAW,gCAAgC,UAAU;GAC/E,UAAU;GAER,WAAW;GACX,mBAAmB,QAAQ;GAE9B,EACD,MACD;EACF,CAAC"}
@@ -5,7 +5,7 @@ import * as _$class_variance_authority_types0 from "class-variance-authority/typ
5
5
 
6
6
  //#region src/components/ui/button.d.ts
7
7
  declare const buttonVariants: (props?: ({
8
- variant?: "default" | "link" | "outline" | "secondary" | "ghost" | "destructive" | null | undefined;
8
+ variant?: "link" | "default" | "outline" | "secondary" | "ghost" | "destructive" | null | undefined;
9
9
  size?: "default" | "icon" | "xs" | "sm" | "lg" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
10
10
  } & _$class_variance_authority_types0.ClassProp) | undefined) => string;
11
11
  declare function Button$1({
@@ -23,16 +23,6 @@ interface CatalogProviderProps {
23
23
  components?: CatalogComponentOverrides;
24
24
  children: ReactNode;
25
25
  }
26
- /**
27
- * Provides customization to the catalog component tree. Nests — inner
28
- * providers override outer keys.
29
- *
30
- * ```tsx
31
- * <CatalogProvider classNames={{ card: "shadow-lg" }}>
32
- * <PipeCatalog />
33
- * </CatalogProvider>
34
- * ```
35
- */
36
26
  declare function CatalogProvider({
37
27
  classNames,
38
28
  components,
@@ -1 +1 @@
1
- {"version":3,"file":"catalog-config-context.d.mts","names":[],"sources":["../../src/context/catalog-config-context.tsx"],"mappings":";;;;;UAIiB,aAAA;EACf,UAAA,GAAa,iBAAA;EACb,UAAA,GAAa,yBAAA;AAAA;AAAA,iBAKC,gBAAA,CAAA,GAAoB,aAAA;;;;;;iBASpB,WAAA,CAAA;EAAc;AAAA;EAAc,QAAA,EAAU,SAAA;AAAA,IAAW,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,UAIhD,oBAAA;EACf,UAAA,GAAa,iBAAA;EACb,UAAA,GAAa,yBAAA;EACb,QAAA,EAAU,SAAA;AAAA;AAPZ;;;;;;;;;;AAAA,iBAoBgB,eAAA,CAAA;EAAkB,UAAA;EAAY,UAAA;EAAY;AAAA,GAAY,oBAAA,GAAoB,oBAAA,CAAA,GAAA,CAAA,OAAA"}
1
+ {"version":3,"file":"catalog-config-context.d.mts","names":[],"sources":["../../src/context/catalog-config-context.tsx"],"mappings":";;;;;UAIiB,aAAA;EACf,UAAA,GAAa,iBAAA;EACb,UAAA,GAAa,yBAAA;AAAA;AAAA,iBAKC,gBAAA,CAAA,GAAoB,aAAA;;;;;;iBASpB,WAAA,CAAA;EAAc;AAAA;EAAc,QAAA,EAAU,SAAA;AAAA,IAAW,oBAAA,CAAA,GAAA,CAAA,OAAA;AAAA,UAIhD,oBAAA;EACf,UAAA,GAAa,iBAAA;EACb,UAAA,GAAa,yBAAA;EACb,QAAA,EAAU,SAAA;AAAA;AAAA,iBAGI,eAAA,CAAA;EAAkB,UAAA;EAAY,UAAA;EAAY;AAAA,GAAY,oBAAA,GAAoB,oBAAA,CAAA,GAAA,CAAA,OAAA"}
@@ -15,16 +15,6 @@ function useCatalogConfig() {
15
15
  function CatalogRoot({ children }) {
16
16
  return /* @__PURE__ */ jsx(TooltipProvider, { children });
17
17
  }
18
- /**
19
- * Provides customization to the catalog component tree. Nests — inner
20
- * providers override outer keys.
21
- *
22
- * ```tsx
23
- * <CatalogProvider classNames={{ card: "shadow-lg" }}>
24
- * <PipeCatalog />
25
- * </CatalogProvider>
26
- * ```
27
- */
28
18
  function CatalogProvider({ classNames, components, children }) {
29
19
  const parent = useCatalogConfig();
30
20
  const merged = {
@@ -1 +1 @@
1
- {"version":3,"file":"catalog-config-context.mjs","names":[],"sources":["../../src/context/catalog-config-context.tsx"],"sourcesContent":["import { createContext, type ReactNode, useContext } from \"react\";\nimport { TooltipProvider } from \"../components/ui/tooltip.js\";\nimport type { CatalogClassNames, CatalogComponentOverrides } from \"../types/catalog-adapters.js\";\n\nexport interface CatalogConfig {\n classNames?: CatalogClassNames;\n components?: CatalogComponentOverrides;\n}\n\nconst CatalogConfigContext = createContext<CatalogConfig>({});\n\nexport function useCatalogConfig(): CatalogConfig {\n return useContext(CatalogConfigContext);\n}\n\n/**\n * Root-level providers required by any catalog component tree (tooltips, etc.).\n * Always mounted by `<PipeCatalog>` / `<SearchCatalog>` / `<SearchesCatalog>`\n * at the outermost layer.\n */\nexport function CatalogRoot({ children }: { children: ReactNode }) {\n return <TooltipProvider>{children}</TooltipProvider>;\n}\n\nexport interface CatalogProviderProps {\n classNames?: CatalogClassNames;\n components?: CatalogComponentOverrides;\n children: ReactNode;\n}\n\n/**\n * Provides customization to the catalog component tree. Nests — inner\n * providers override outer keys.\n *\n * ```tsx\n * <CatalogProvider classNames={{ card: \"shadow-lg\" }}>\n * <PipeCatalog />\n * </CatalogProvider>\n * ```\n */\nexport function CatalogProvider({ classNames, components, children }: CatalogProviderProps) {\n const parent = useCatalogConfig();\n const merged: CatalogConfig = {\n classNames: { ...parent.classNames, ...classNames },\n components: { ...parent.components, ...components },\n };\n return <CatalogConfigContext.Provider value={merged}>{children}</CatalogConfigContext.Provider>;\n}\n"],"mappings":";;;;;AASA,MAAM,uBAAuB,cAA6B,EAAE,CAAC;AAE7D,SAAgB,mBAAkC;AAChD,QAAO,WAAW,qBAAqB;;;;;;;AAQzC,SAAgB,YAAY,EAAE,YAAqC;AACjE,QAAO,oBAAC,iBAAD,EAAkB,UAA2B;;;;;;;;;;;;AAmBtD,SAAgB,gBAAgB,EAAE,YAAY,YAAY,YAAkC;CAC1F,MAAM,SAAS,kBAAkB;CACjC,MAAM,SAAwB;EAC5B,YAAY;GAAE,GAAG,OAAO;GAAY,GAAG;GAAY;EACnD,YAAY;GAAE,GAAG,OAAO;GAAY,GAAG;GAAY;EACpD;AACD,QAAO,oBAAC,qBAAqB,UAAtB;EAA+B,OAAO;EAAS;EAAyC"}
1
+ {"version":3,"file":"catalog-config-context.mjs","names":[],"sources":["../../src/context/catalog-config-context.tsx"],"sourcesContent":["import { createContext, type ReactNode, useContext } from \"react\";\nimport { TooltipProvider } from \"../components/ui/tooltip.js\";\nimport type { CatalogClassNames, CatalogComponentOverrides } from \"../types/catalog-adapters.js\";\n\nexport interface CatalogConfig {\n classNames?: CatalogClassNames;\n components?: CatalogComponentOverrides;\n}\n\nconst CatalogConfigContext = createContext<CatalogConfig>({});\n\nexport function useCatalogConfig(): CatalogConfig {\n return useContext(CatalogConfigContext);\n}\n\n/**\n * Root-level providers required by any catalog component tree (tooltips, etc.).\n * Always mounted by `<PipeCatalog>` / `<SearchCatalog>` / `<SearchesCatalog>`\n * at the outermost layer.\n */\nexport function CatalogRoot({ children }: { children: ReactNode }) {\n return <TooltipProvider>{children}</TooltipProvider>;\n}\n\nexport interface CatalogProviderProps {\n classNames?: CatalogClassNames;\n components?: CatalogComponentOverrides;\n children: ReactNode;\n}\n\nexport function CatalogProvider({ classNames, components, children }: CatalogProviderProps) {\n const parent = useCatalogConfig();\n const merged: CatalogConfig = {\n classNames: { ...parent.classNames, ...classNames },\n components: { ...parent.components, ...components },\n };\n return <CatalogConfigContext.Provider value={merged}>{children}</CatalogConfigContext.Provider>;\n}\n"],"mappings":";;;;;AASA,MAAM,uBAAuB,cAA6B,EAAE,CAAC;AAE7D,SAAgB,mBAAkC;AAChD,QAAO,WAAW,qBAAqB;;;;;;;AAQzC,SAAgB,YAAY,EAAE,YAAqC;AACjE,QAAO,oBAAC,iBAAD,EAAkB,UAA2B;;AAStD,SAAgB,gBAAgB,EAAE,YAAY,YAAY,YAAkC;CAC1F,MAAM,SAAS,kBAAkB;CACjC,MAAM,SAAwB;EAC5B,YAAY;GAAE,GAAG,OAAO;GAAY,GAAG;GAAY;EACnD,YAAY;GAAE,GAAG,OAAO;GAAY,GAAG;GAAY;EACpD;AACD,QAAO,oBAAC,qBAAqB,UAAtB;EAA+B,OAAO;EAAS;EAAyC"}
package/dist/index.mjs CHANGED
@@ -33,6 +33,7 @@ import { PricingBadge } from "./widgets/pricing-badge.mjs";
33
33
  import { ProviderLogo } from "./widgets/provider-logo.mjs";
34
34
  import { WidgetView } from "./widgets/widget-view.mjs";
35
35
  import { WidgetStrip } from "./widgets/widget-strip.mjs";
36
+ import { AvatarGroup } from "./widgets/avatar-group.mjs";
36
37
  import { defaultAdapters } from "./components/defaults/adapters/index.mjs";
37
38
  import { FieldRenderer } from "./components/field-renderer.mjs";
38
39
  import { PipeFormField } from "./components/compound/pipe-form/field.mjs";
@@ -86,7 +87,6 @@ import { SearchesCatalog } from "./components/compound/searches-catalog/root.mjs
86
87
  import { SearchesCatalogTagFilter } from "./components/compound/searches-catalog/tag-filter.mjs";
87
88
  import { CatalogCopyId, CatalogCreditBadge, CatalogDocsBadge, CatalogFieldBadge } from "./components/defaults/catalog/card-derived.mjs";
88
89
  import { CatalogCategorySection } from "./components/defaults/catalog/category-section.mjs";
89
- import { AvatarGroup } from "./widgets/avatar-group.mjs";
90
90
  import { CatalogProviderAvatars } from "./components/defaults/catalog/provider-avatars.mjs";
91
91
 
92
92
  export { AvatarGroup, CatalogCard, CatalogCardBadge, CatalogCardBadges, CatalogCardDescription, CatalogCardHeader, CatalogCardTitle, CatalogCategorySection, CatalogCopyId, CatalogCreditBadge, CatalogDocsBadge, CatalogFieldBadge, CatalogProvider, CatalogProviderAvatars, CatalogRoot, EmojiGlyph, FieldRenderer, FieldTypeBadge, FormProvider, FormRoot, IconGlyph, LogoUrl, PipeCatalog, PipeCatalogActiveFilters, PipeCatalogCard, PipeCatalogCardContext, PipeCatalogCategoryFilter, PipeCatalogColumnFilter, PipeCatalogColumnFilters, PipeCatalogContext, PipeCatalogEmpty, PipeCatalogInputFieldFilter, PipeCatalogList, PipeCatalogOutputFieldFilter, PipeCatalogProviderFilter, PipeCatalogSearchFilter, PipeCatalogTagFilter, PipeForm, PipeFormContent, PipeFormContext, PipeFormErrors, PipeFormField, PipeFormFooter, PipeFormGroup, PipeFormHeader, PipeFormSection, PipeFormSubmitButton, PipeFormTitle, PricingBadge, ProviderLogo, SearchCatalog, SearchCatalogActiveFilters, SearchCatalogCard, SearchCatalogCardContext, SearchCatalogCategoryFilter, SearchCatalogColumnFilter, SearchCatalogColumnFilters, SearchCatalogContext, SearchCatalogEmpty, SearchCatalogList, SearchCatalogOutputFieldFilter, SearchCatalogProviderFilter, SearchCatalogSearchFilter, SearchCatalogTagFilter, SearchForm, SearchFormContent, SearchFormContext, SearchFormErrors, SearchFormField, SearchFormFooter, SearchFormGroup, SearchFormHeader, SearchFormSection, SearchFormSubmitButton, SearchFormTitle, SearchesCatalog, SearchesCatalogActiveFilters, SearchesCatalogCard, SearchesCatalogCardContext, SearchesCatalogCategoryFilter, SearchesCatalogColumnFilter, SearchesCatalogColumnFilters, SearchesCatalogContext, SearchesCatalogEmpty, SearchesCatalogList, SearchesCatalogOutputFieldFilter, SearchesCatalogProviderFilter, SearchesCatalogSearchFilter, SearchesCatalogTagFilter, WidgetStrip, WidgetView, defaultAdapters, fuzzyFilter, getFieldStatusIcon, getFieldTypeIcon, useCatalogConfig, useFieldError, usePipeCatalogCard, usePipeCatalogContext, usePipeCatalogTable, usePipeForm, usePipeFormContext, usePortalContainer, useSearchCatalogCard, useSearchCatalogContext, useSearchCatalogTable, useSearchForm, useSearchFormContext, useSearchesCatalogCard, useSearchesCatalogContext, useSearchesCatalogTable };
@@ -65,7 +65,6 @@
65
65
  --pz-tracking-widest: 0.1em;
66
66
  --pz-leading-tight: 1.25;
67
67
  --pz-radius-md: calc(var(--p0-radius) - 2px);
68
- --pz-ease-out: cubic-bezier(0, 0, 0.2, 1);
69
68
  --pz-animate-spin: spin 1s linear infinite;
70
69
  --pz-animate-pulse: pulse 2s cubic-bezier(0.4, 0, 0.6, 1) infinite;
71
70
  --pz-blur-xs: 4px;
@@ -406,9 +405,6 @@
406
405
  .pz\:w-72 {
407
406
  width: calc(var(--pz-spacing) * 72);
408
407
  }
409
- .pz\:w-80 {
410
- width: calc(var(--pz-spacing) * 80);
411
- }
412
408
  .pz\:w-auto {
413
409
  width: auto;
414
410
  }
@@ -500,9 +496,6 @@
500
496
  .pz\:rotate-45 {
501
497
  rotate: 45deg;
502
498
  }
503
- .pz\:rotate-180 {
504
- rotate: 180deg;
505
- }
506
499
  .pz\:animate-pulse {
507
500
  animation: var(--pz-animate-pulse);
508
501
  }
@@ -1008,9 +1001,6 @@
1008
1001
  .pz\:pt-2 {
1009
1002
  padding-top: calc(var(--pz-spacing) * 2);
1010
1003
  }
1011
- .pz\:pt-3 {
1012
- padding-top: calc(var(--pz-spacing) * 3);
1013
- }
1014
1004
  .pz\:pr-0 {
1015
1005
  padding-right: calc(var(--pz-spacing) * 0);
1016
1006
  }
@@ -1044,9 +1034,6 @@
1044
1034
  .pz\:pb-3 {
1045
1035
  padding-bottom: calc(var(--pz-spacing) * 3);
1046
1036
  }
1047
- .pz\:pb-3\.5 {
1048
- padding-bottom: calc(var(--pz-spacing) * 3.5);
1049
- }
1050
1037
  .pz\:pl-0 {
1051
1038
  padding-left: calc(var(--pz-spacing) * 0);
1052
1039
  }
@@ -1255,12 +1242,6 @@
1255
1242
  color: color-mix(in oklab, var(--p0-muted-foreground) 70%, transparent);
1256
1243
  }
1257
1244
  }
1258
- .pz\:text-muted-foreground\/80 {
1259
- color: var(--p0-muted-foreground);
1260
- @supports (color: color-mix(in lab, red, red)) {
1261
- color: color-mix(in oklab, var(--p0-muted-foreground) 80%, transparent);
1262
- }
1263
- }
1264
1245
  .pz\:text-orange-700 {
1265
1246
  color: var(--pz-color-orange-700);
1266
1247
  }
@@ -1385,16 +1366,6 @@
1385
1366
  outline-offset: 2px;
1386
1367
  }
1387
1368
  }
1388
- .pz\:transition-\[height\,opacity\] {
1389
- transition-property: height,opacity;
1390
- transition-timing-function: var(--tw-ease, var(--pz-default-transition-timing-function));
1391
- transition-duration: var(--tw-duration, var(--pz-default-transition-duration));
1392
- }
1393
- .pz\:transition-\[height\] {
1394
- transition-property: height;
1395
- transition-timing-function: var(--tw-ease, var(--pz-default-transition-timing-function));
1396
- transition-duration: var(--tw-duration, var(--pz-default-transition-duration));
1397
- }
1398
1369
  .pz\:transition-all {
1399
1370
  transition-property: all;
1400
1371
  transition-timing-function: var(--tw-ease, var(--pz-default-transition-timing-function));
@@ -1426,14 +1397,6 @@
1426
1397
  --tw-duration: 150ms;
1427
1398
  transition-duration: 150ms;
1428
1399
  }
1429
- .pz\:duration-200 {
1430
- --tw-duration: 200ms;
1431
- transition-duration: 200ms;
1432
- }
1433
- .pz\:ease-out {
1434
- --tw-ease: var(--pz-ease-out);
1435
- transition-timing-function: var(--pz-ease-out);
1436
- }
1437
1400
  .pz\:outline-none {
1438
1401
  --tw-outline-style: none;
1439
1402
  outline-style: none;
@@ -1448,25 +1411,12 @@
1448
1411
  .pz\:duration-150 {
1449
1412
  animation-duration: 150ms;
1450
1413
  }
1451
- .pz\:duration-200 {
1452
- animation-duration: 200ms;
1453
- }
1454
- .pz\:ease-out {
1455
- animation-timing-function: cubic-bezier(0, 0, 0.2, 1);
1456
- }
1457
1414
  .pz\:not-last\:border-b {
1458
1415
  &:not(*:last-child) {
1459
1416
  border-bottom-style: var(--tw-border-style);
1460
1417
  border-bottom-width: 1px;
1461
1418
  }
1462
1419
  }
1463
- .pz\:group-hover\/prov\:opacity-100 {
1464
- &:is(:where(.pz\:group\/prov):hover *) {
1465
- @media (hover: hover) {
1466
- opacity: 100%;
1467
- }
1468
- }
1469
- }
1470
1420
  .pz\:group-has-disabled\/field\:opacity-50 {
1471
1421
  &:is(:where(.pz\:group\/field):has(*:disabled) *) {
1472
1422
  opacity: 50%;
@@ -3935,10 +3885,6 @@
3935
3885
  syntax: "*";
3936
3886
  inherits: false;
3937
3887
  }
3938
- @property --tw-ease {
3939
- syntax: "*";
3940
- inherits: false;
3941
- }
3942
3888
  @property --tw-content {
3943
3889
  syntax: "*";
3944
3890
  initial-value: "";
@@ -4083,7 +4029,6 @@
4083
4029
  --tw-ring-offset-color: #fff;
4084
4030
  --tw-ring-offset-shadow: 0 0 #0000;
4085
4031
  --tw-duration: initial;
4086
- --tw-ease: initial;
4087
4032
  --tw-content: "";
4088
4033
  --tw-outline-style: solid;
4089
4034
  --tw-backdrop-blur: initial;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pipe0/react",
3
- "version": "0.0.7",
3
+ "version": "0.0.9",
4
4
  "description": "React component library for building forms and catalogs powered by pipe0 pipes and searches.",
5
5
  "license": "MIT",
6
6
  "author": "pipe0",
@@ -87,7 +87,7 @@
87
87
  "lucide-react": "^0.475.0",
88
88
  "swr": "^2.4.1",
89
89
  "tailwind-merge": "^3.3.1",
90
- "@pipe0/base": "0.0.7"
90
+ "@pipe0/base": "0.0.9"
91
91
  },
92
92
  "devDependencies": {
93
93
  "@dnd-kit/core": "^6.3.1",