@pipe0/react 0.0.10 → 0.0.12

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.12
4
+
5
+ ### Patch Changes
6
+
7
+ - 6c621bd: Fix missing deps
8
+ - Updated dependencies [6c621bd]
9
+ - @pipe0/base@0.0.12
10
+
11
+ ## 0.0.11
12
+
13
+ ### Patch Changes
14
+
15
+ - Prepare v1 changes
16
+ - Updated dependencies
17
+ - @pipe0/base@0.0.11
18
+
3
19
  ## 0.0.10
4
20
 
5
21
  ### Patch Changes
@@ -1 +1 @@
1
- {"version":3,"file":"provider-filter.mjs","names":[],"sources":["../../../../src/components/compound/search-catalog/provider-filter.tsx"],"sourcesContent":["import { useRender } from \"@base-ui/react/use-render\";\nimport { getProviderEntry, type ProviderName } from \"@pipe0/base\";\nimport { Building2 } from \"lucide-react\";\nimport type { ReactNode } from \"react\";\nimport { useSearchCatalogContext } from \"../../../context/search-catalog-context.js\";\nimport type { FilterSelectOption } from \"../../defaults/catalog/filter-select.js\";\nimport { type ColumnFilterState, SearchCatalogColumnFilter } from \"./column-filter.js\";\n\nexport interface SearchCatalogProviderFilterProps {\n options?: ReadonlyArray<FilterSelectOption>;\n placeholder?: ReactNode;\n className?: string;\n render?: useRender.ComponentProps<\"div\", ColumnFilterState>[\"render\"];\n}\n\nconst DEFAULT_PLACEHOLDER = (\n <span className=\"pz:inline-flex pz:items-center pz:gap-1.5\">\n <Building2 className=\"pz:size-4\" /> Provider\n </span>\n);\n\nexport function SearchCatalogProviderFilter({\n options,\n placeholder = DEFAULT_PLACEHOLDER,\n className,\n render,\n}: SearchCatalogProviderFilterProps) {\n const ctx = useSearchCatalogContext();\n const resolvedOptions =\n options ??\n ctx.sortedProviderEntries.map(([name]) => ({\n label: name,\n value: name,\n imageSrc: getProviderEntry(name as ProviderName)?.logoUrl,\n }));\n\n return (\n <SearchCatalogColumnFilter\n id=\"providers\"\n placeholder={placeholder}\n options={resolvedOptions}\n className={className}\n render={render}\n />\n );\n}\n"],"mappings":";;;;;;;AAeA,MAAM,sBACJ,qBAAC,QAAD;CAAM,WAAU;WAAhB,CACE,oBAAC,WAAD,EAAW,WAAU,aAAc,eAC9B;;AAGT,SAAgB,4BAA4B,EAC1C,SACA,cAAc,qBACd,WACA,UACmC;CACnC,MAAM,MAAM,yBAAyB;AASrC,QACE,oBAAC,2BAAD;EACE,IAAG;EACU;EACb,SAXF,WACA,IAAI,sBAAsB,KAAK,CAAC,WAAW;GACzC,OAAO;GACP,OAAO;GACP,UAAU,iBAAiB,KAAqB,EAAE;GACnD,EAAE;EAOU;EACH;EACR"}
1
+ {"version":3,"file":"provider-filter.mjs","names":[],"sources":["../../../../src/components/compound/search-catalog/provider-filter.tsx"],"sourcesContent":["import type { useRender } from \"@base-ui/react/use-render\";\nimport { getProviderEntry, type ProviderName } from \"@pipe0/base\";\nimport { Building2 } from \"lucide-react\";\nimport type { ReactNode } from \"react\";\nimport { useSearchCatalogContext } from \"../../../context/search-catalog-context.js\";\nimport type { FilterSelectOption } from \"../../defaults/catalog/filter-select.js\";\nimport { type ColumnFilterState, SearchCatalogColumnFilter } from \"./column-filter.js\";\n\nexport interface SearchCatalogProviderFilterProps {\n options?: ReadonlyArray<FilterSelectOption>;\n placeholder?: ReactNode;\n className?: string;\n render?: useRender.ComponentProps<\"div\", ColumnFilterState>[\"render\"];\n}\n\nconst DEFAULT_PLACEHOLDER = (\n <span className=\"pz:inline-flex pz:items-center pz:gap-1.5\">\n <Building2 className=\"pz:size-4\" /> Provider\n </span>\n);\n\nexport function SearchCatalogProviderFilter({\n options,\n placeholder = DEFAULT_PLACEHOLDER,\n className,\n render,\n}: SearchCatalogProviderFilterProps) {\n const ctx = useSearchCatalogContext();\n const resolvedOptions =\n options ??\n ctx.sortedProviderEntries.map(([name]) => ({\n label: name,\n value: name,\n imageSrc: getProviderEntry(name as ProviderName)?.logoUrl,\n }));\n\n return (\n <SearchCatalogColumnFilter\n id=\"providers\"\n placeholder={placeholder}\n options={resolvedOptions}\n className={className}\n render={render}\n />\n );\n}\n"],"mappings":";;;;;;;AAeA,MAAM,sBACJ,qBAAC,QAAD;CAAM,WAAU;WAAhB,CACE,oBAAC,WAAD,EAAW,WAAU,aAAc,eAC9B;;AAGT,SAAgB,4BAA4B,EAC1C,SACA,cAAc,qBACd,WACA,UACmC;CACnC,MAAM,MAAM,yBAAyB;AASrC,QACE,oBAAC,2BAAD;EACE,IAAG;EACU;EACb,SAXF,WACA,IAAI,sBAAsB,KAAK,CAAC,WAAW;GACzC,OAAO;GACP,OAAO;GACP,UAAU,iBAAiB,KAAqB,EAAE;GACnD,EAAE;EAOU;EACH;EACR"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../../../../src/components/defaults/adapters/index.ts"],"mappings":";;;;;AAoCA;;cAAa,eAAA,EAgC2B,OAAA,CAAQ,eAAA"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../../../../src/components/defaults/adapters/index.ts"],"mappings":";;;;;AAqCA;;cAAa,eAAA,EAiC2B,OAAA,CAAQ,eAAA"}
@@ -18,6 +18,7 @@ import { MultiCreateInputAdapter } from "./multi-create-input.mjs";
18
18
  import { MultiSelectInputAdapter } from "./multi-select-input.mjs";
19
19
  import { NumberInputAdapter } from "./number-input.mjs";
20
20
  import { OrderedMultiCreateInputAdapter } from "./ordered-multi-create-input.mjs";
21
+ import { TaggedOrderedMultiCreateInputAdapter } from "./tagged-ordered-multi-create-input.mjs";
21
22
  import { OutputFieldInputAdapter } from "./output-field-input.mjs";
22
23
  import { PipesRunIfInputAdapter } from "./pipes-run-if-input.mjs";
23
24
  import { PromptInputAdapter } from "./prompt-input.mjs";
@@ -54,6 +55,7 @@ const defaultAdapters = {
54
55
  exact_range_input: ExactRangeInputAdapter,
55
56
  min_max_int_input: MinMaxIntInputAdapter,
56
57
  ordered_multi_create_input: OrderedMultiCreateInputAdapter,
58
+ tagged_ordered_multi_create_input: TaggedOrderedMultiCreateInputAdapter,
57
59
  prompt_input: PromptInputAdapter,
58
60
  template_input: TemplateInputAdapter,
59
61
  tagged_text_input: TaggedTextInputAdapter,
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/components/defaults/adapters/index.ts"],"sourcesContent":["import type { FieldAdapterMap } from \"../../../types/adapters.js\";\nimport { AsyncIncludeExcludeSelectInputAdapter } from \"./async-include-exclude-select-input.js\";\nimport { AsyncMultiSelectInputAdapter } from \"./async-multi-select-input.js\";\nimport { BooleanInputAdapter } from \"./boolean-input.js\";\nimport { ConnectorInputAdapter } from \"./connector-input.js\";\nimport { ContextSelectInputAdapter } from \"./context-select-input.js\";\nimport { CursorPaginationInputAdapter } from \"./cursor-pagination-input.js\";\nimport { DateRangeInputAdapter } from \"./date-range-input.js\";\nimport { ExactRangeInputAdapter } from \"./exact-range-input.js\";\nimport { FieldsSelectInputAdapter } from \"./fields-select-input.js\";\nimport { IncludeExcludeInputAdapter } from \"./include-exclude-input.js\";\nimport { IncludeExcludeSelectInputAdapter } from \"./include-exclude-select-input.js\";\nimport { IntInputAdapter } from \"./int-input.js\";\nimport { JsonExtractionInputAdapter } from \"./json-extraction-input.js\";\nimport { JsonSchemaInputAdapter } from \"./json-schema-input.js\";\nimport { KeyValueListInputAdapter } from \"./key-value-list-input.js\";\nimport { MinMaxIntInputAdapter } from \"./min-max-int-input.js\";\nimport { MultiCreateInputAdapter } from \"./multi-create-input.js\";\nimport { MultiSelectInputAdapter } from \"./multi-select-input.js\";\nimport { NumberInputAdapter } from \"./number-input.js\";\nimport { OrderedMultiCreateInputAdapter } from \"./ordered-multi-create-input.js\";\nimport { OutputFieldInputAdapter } from \"./output-field-input.js\";\nimport { PipesRunIfInputAdapter } from \"./pipes-run-if-input.js\";\nimport { PromptInputAdapter } from \"./prompt-input.js\";\nimport { ProvidersInputAdapter } from \"./providers-input.js\";\nimport { RangeInputAdapter } from \"./range-input.js\";\nimport { SelectInputAdapter } from \"./select-input.js\";\nimport { TaggedTextInputAdapter } from \"./tagged-text-input.js\";\nimport { TemplateInputAdapter } from \"./template-input.js\";\nimport { TextInputAdapter } from \"./text-input.js\";\nimport { TextareaInputAdapter } from \"./textarea-input.js\";\n\n/**\n * Default field adapters for all known field kinds.\n * Users can override any of these via `<FormProvider adapters={...}>`.\n */\nexport const defaultAdapters = {\n text_input: TextInputAdapter,\n textarea_input: TextareaInputAdapter,\n int_input: IntInputAdapter,\n number_input: NumberInputAdapter,\n select_input: SelectInputAdapter,\n boolean_input: BooleanInputAdapter,\n nullable_boolean_input: BooleanInputAdapter,\n range_input: RangeInputAdapter,\n date_range_input: DateRangeInputAdapter,\n multi_select_input: MultiSelectInputAdapter,\n include_exclude_input: IncludeExcludeInputAdapter,\n multi_create_input: MultiCreateInputAdapter,\n context_select_input: ContextSelectInputAdapter,\n async_multi_select_input: AsyncMultiSelectInputAdapter,\n async_include_exclude_select_input: AsyncIncludeExcludeSelectInputAdapter,\n include_exclude_select_input: IncludeExcludeSelectInputAdapter,\n exact_range_input: ExactRangeInputAdapter,\n min_max_int_input: MinMaxIntInputAdapter,\n ordered_multi_create_input: OrderedMultiCreateInputAdapter,\n prompt_input: PromptInputAdapter,\n template_input: TemplateInputAdapter,\n tagged_text_input: TaggedTextInputAdapter,\n key_value_list_input: KeyValueListInputAdapter,\n json_schema_input: JsonSchemaInputAdapter,\n json_extraction_input: JsonExtractionInputAdapter,\n pipes_run_if_input: PipesRunIfInputAdapter,\n connector_input: ConnectorInputAdapter,\n providers_input: ProvidersInputAdapter,\n fields_select_input: FieldsSelectInputAdapter,\n output_field_input: OutputFieldInputAdapter,\n cursor_pagination_metadata: CursorPaginationInputAdapter,\n} satisfies Partial<FieldAdapterMap> as Partial<FieldAdapterMap>;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoCA,MAAa,kBAAkB;CAC7B,YAAY;CACZ,gBAAgB;CAChB,WAAW;CACX,cAAc;CACd,cAAc;CACd,eAAe;CACf,wBAAwB;CACxB,aAAa;CACb,kBAAkB;CAClB,oBAAoB;CACpB,uBAAuB;CACvB,oBAAoB;CACpB,sBAAsB;CACtB,0BAA0B;CAC1B,oCAAoC;CACpC,8BAA8B;CAC9B,mBAAmB;CACnB,mBAAmB;CACnB,4BAA4B;CAC5B,cAAc;CACd,gBAAgB;CAChB,mBAAmB;CACnB,sBAAsB;CACtB,mBAAmB;CACnB,uBAAuB;CACvB,oBAAoB;CACpB,iBAAiB;CACjB,iBAAiB;CACjB,qBAAqB;CACrB,oBAAoB;CACpB,4BAA4B;CAC7B"}
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../../../../src/components/defaults/adapters/index.ts"],"sourcesContent":["import type { FieldAdapterMap } from \"../../../types/adapters.js\";\nimport { AsyncIncludeExcludeSelectInputAdapter } from \"./async-include-exclude-select-input.js\";\nimport { AsyncMultiSelectInputAdapter } from \"./async-multi-select-input.js\";\nimport { BooleanInputAdapter } from \"./boolean-input.js\";\nimport { ConnectorInputAdapter } from \"./connector-input.js\";\nimport { ContextSelectInputAdapter } from \"./context-select-input.js\";\nimport { CursorPaginationInputAdapter } from \"./cursor-pagination-input.js\";\nimport { DateRangeInputAdapter } from \"./date-range-input.js\";\nimport { ExactRangeInputAdapter } from \"./exact-range-input.js\";\nimport { FieldsSelectInputAdapter } from \"./fields-select-input.js\";\nimport { IncludeExcludeInputAdapter } from \"./include-exclude-input.js\";\nimport { IncludeExcludeSelectInputAdapter } from \"./include-exclude-select-input.js\";\nimport { IntInputAdapter } from \"./int-input.js\";\nimport { JsonExtractionInputAdapter } from \"./json-extraction-input.js\";\nimport { JsonSchemaInputAdapter } from \"./json-schema-input.js\";\nimport { KeyValueListInputAdapter } from \"./key-value-list-input.js\";\nimport { MinMaxIntInputAdapter } from \"./min-max-int-input.js\";\nimport { MultiCreateInputAdapter } from \"./multi-create-input.js\";\nimport { MultiSelectInputAdapter } from \"./multi-select-input.js\";\nimport { NumberInputAdapter } from \"./number-input.js\";\nimport { OrderedMultiCreateInputAdapter } from \"./ordered-multi-create-input.js\";\nimport { TaggedOrderedMultiCreateInputAdapter } from \"./tagged-ordered-multi-create-input.js\";\nimport { OutputFieldInputAdapter } from \"./output-field-input.js\";\nimport { PipesRunIfInputAdapter } from \"./pipes-run-if-input.js\";\nimport { PromptInputAdapter } from \"./prompt-input.js\";\nimport { ProvidersInputAdapter } from \"./providers-input.js\";\nimport { RangeInputAdapter } from \"./range-input.js\";\nimport { SelectInputAdapter } from \"./select-input.js\";\nimport { TaggedTextInputAdapter } from \"./tagged-text-input.js\";\nimport { TemplateInputAdapter } from \"./template-input.js\";\nimport { TextInputAdapter } from \"./text-input.js\";\nimport { TextareaInputAdapter } from \"./textarea-input.js\";\n\n/**\n * Default field adapters for all known field kinds.\n * Users can override any of these via `<FormProvider adapters={...}>`.\n */\nexport const defaultAdapters = {\n text_input: TextInputAdapter,\n textarea_input: TextareaInputAdapter,\n int_input: IntInputAdapter,\n number_input: NumberInputAdapter,\n select_input: SelectInputAdapter,\n boolean_input: BooleanInputAdapter,\n nullable_boolean_input: BooleanInputAdapter,\n range_input: RangeInputAdapter,\n date_range_input: DateRangeInputAdapter,\n multi_select_input: MultiSelectInputAdapter,\n include_exclude_input: IncludeExcludeInputAdapter,\n multi_create_input: MultiCreateInputAdapter,\n context_select_input: ContextSelectInputAdapter,\n async_multi_select_input: AsyncMultiSelectInputAdapter,\n async_include_exclude_select_input: AsyncIncludeExcludeSelectInputAdapter,\n include_exclude_select_input: IncludeExcludeSelectInputAdapter,\n exact_range_input: ExactRangeInputAdapter,\n min_max_int_input: MinMaxIntInputAdapter,\n ordered_multi_create_input: OrderedMultiCreateInputAdapter,\n tagged_ordered_multi_create_input: TaggedOrderedMultiCreateInputAdapter,\n prompt_input: PromptInputAdapter,\n template_input: TemplateInputAdapter,\n tagged_text_input: TaggedTextInputAdapter,\n key_value_list_input: KeyValueListInputAdapter,\n json_schema_input: JsonSchemaInputAdapter,\n json_extraction_input: JsonExtractionInputAdapter,\n pipes_run_if_input: PipesRunIfInputAdapter,\n connector_input: ConnectorInputAdapter,\n providers_input: ProvidersInputAdapter,\n fields_select_input: FieldsSelectInputAdapter,\n output_field_input: OutputFieldInputAdapter,\n cursor_pagination_metadata: CursorPaginationInputAdapter,\n} satisfies Partial<FieldAdapterMap> as Partial<FieldAdapterMap>;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqCA,MAAa,kBAAkB;CAC7B,YAAY;CACZ,gBAAgB;CAChB,WAAW;CACX,cAAc;CACd,cAAc;CACd,eAAe;CACf,wBAAwB;CACxB,aAAa;CACb,kBAAkB;CAClB,oBAAoB;CACpB,uBAAuB;CACvB,oBAAoB;CACpB,sBAAsB;CACtB,0BAA0B;CAC1B,oCAAoC;CACpC,8BAA8B;CAC9B,mBAAmB;CACnB,mBAAmB;CACnB,4BAA4B;CAC5B,mCAAmC;CACnC,cAAc;CACd,gBAAgB;CAChB,mBAAmB;CACnB,sBAAsB;CACtB,mBAAmB;CACnB,uBAAuB;CACvB,oBAAoB;CACpB,iBAAiB;CACjB,iBAAiB;CACjB,qBAAqB;CACrB,oBAAoB;CACpB,4BAA4B;CAC7B"}
@@ -114,7 +114,7 @@ function ProviderRow({ value, index, label, widgets, onRemove }) {
114
114
  opacity: isDragging ? .6 : 1
115
115
  };
116
116
  const { providerName, leading, pricing } = splitWidgets(widgets);
117
- const orderLabel = String(index + 1).padStart(2, "0");
117
+ const orderLabel = String(index + 1);
118
118
  return /* @__PURE__ */ jsxs("li", {
119
119
  ref: setNodeRef,
120
120
  style,
@@ -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 { 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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"}
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);\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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"}
@@ -0,0 +1,343 @@
1
+ import { cn } from "../../../lib/utils.mjs";
2
+ import { Button } from "../../ui/button.mjs";
3
+ import { IconGripVertical } from "../../internal/icons.mjs";
4
+ import { useDebouncedFn } from "../../../hooks/use-debounced-fn.mjs";
5
+ import { FieldTypeBadge } from "../../../widgets/field-type-badge.mjs";
6
+ import { WidgetStrip } from "../../../widgets/widget-strip.mjs";
7
+ import { Combobox, ComboboxChips, ComboboxChipsInput, ComboboxContent, ComboboxEmpty, ComboboxGroup, ComboboxItem, ComboboxLabel, ComboboxList, ComboboxTrigger, useComboboxAnchor } from "../../ui/combobox.mjs";
8
+ import { filterOptions } from "../../internal/multi-select-popover-trigger.mjs";
9
+ import { useId, useMemo, useRef, useState } from "react";
10
+ import { jsx, jsxs } from "react/jsx-runtime";
11
+ import { XIcon } from "lucide-react";
12
+ import { DndContext, KeyboardSensor, PointerSensor, closestCenter, useSensor, useSensors } from "@dnd-kit/core";
13
+ import { SortableContext, horizontalListSortingStrategy, useSortable } from "@dnd-kit/sortable";
14
+ import useSWR from "swr";
15
+
16
+ //#region src/components/defaults/adapters/tagged-ordered-multi-create-input.tsx
17
+ /**
18
+ * Detects whether a raw value is a single, exclusive Liquid field reference
19
+ * (e.g. `"{{ company_domain }}"` or `"{{ field | filter }}"`). Mixed content
20
+ * such as `"Head of {{ company }}"` returns false and is treated as text.
21
+ */
22
+ const PURE_TAG_RE = /^\s*\{\{\s*([a-zA-Z_][a-zA-Z0-9_.]*)(?:\s*\|\s*[^}]+)?\s*\}\}\s*$/;
23
+ function parseChip(raw) {
24
+ const m = raw.match(PURE_TAG_RE);
25
+ if (m) return {
26
+ kind: "field",
27
+ fieldName: m[1],
28
+ raw
29
+ };
30
+ return {
31
+ kind: "text",
32
+ text: raw,
33
+ raw
34
+ };
35
+ }
36
+ /**
37
+ * Sky-blue pill matching `TagChipDecoration`'s field chip styling so a
38
+ * field-reference chip outside tiptap reads identically to one inside
39
+ * `LiquidEditor`.
40
+ */
41
+ const FIELD_CHIP_CLASS = "pz:flex pz:h-[calc(--spacing(5.25))] pz:w-fit pz:items-center pz:gap-1 pz:rounded-sm pz:bg-sky-100 pz:pl-0.5 pz:pr-0 pz:text-xs pz:font-medium pz:whitespace-nowrap pz:text-sky-900";
42
+ const TEXT_CHIP_CLASS = "pz:flex pz:h-[calc(--spacing(5.25))] pz:w-fit pz:items-center pz:gap-1 pz:rounded-sm pz:bg-muted pz:pl-0.5 pz:pr-0 pz:text-xs pz:font-medium pz:whitespace-nowrap pz:text-foreground";
43
+ function TaggedOrderedMultiCreateInputAdapter(field) {
44
+ const { items, setItems, options, loadOptions, inputFields, meta } = field;
45
+ const maxItems = meta.maxItems;
46
+ const placeholder = meta.placeholder;
47
+ const [input, setInput] = useState("");
48
+ const [debouncedQuery, setDebouncedQuery] = useState("");
49
+ const [open, setOpen] = useState(false);
50
+ const isAsync = typeof loadOptions === "function";
51
+ const debouncedSetQuery = useDebouncedFn((q) => setDebouncedQuery(q), 300);
52
+ const instanceId = useId();
53
+ const { data: asyncResults = null, isLoading: swrIsLoading, isValidating: swrIsValidating } = useSWR(loadOptions && (open || debouncedQuery !== "") ? [instanceId, debouncedQuery] : null, async ([, q]) => {
54
+ if (!loadOptions) return [];
55
+ return (await loadOptions(q)).filter((o) => !!o.value);
56
+ }, { keepPreviousData: true });
57
+ const loading = swrIsLoading || swrIsValidating;
58
+ const trimmedInput = input.trim();
59
+ const fieldRefItems = useMemo(() => {
60
+ if (!inputFields?.length) return [];
61
+ const q = trimmedInput.toLowerCase();
62
+ return inputFields.filter((f) => !q || f.resolvedName.toLowerCase().includes(q)).map((f) => ({
63
+ value: `{{ ${f.resolvedName} }}`,
64
+ label: f.resolvedName,
65
+ kind: "field"
66
+ }));
67
+ }, [inputFields, trimmedInput]);
68
+ const suggestionItems = useMemo(() => {
69
+ const source = isAsync ? asyncResults ?? [] : options ?? [];
70
+ return (isAsync ? source : filterOptions(source, input)).map((o) => ({
71
+ value: o.value,
72
+ label: o.label,
73
+ kind: "text",
74
+ widgets: o.widgets
75
+ }));
76
+ }, [
77
+ isAsync,
78
+ asyncResults,
79
+ options,
80
+ input
81
+ ]);
82
+ const matchesExistingSuggestion = useMemo(() => suggestionItems.some((o) => o.value.toLowerCase() === trimmedInput.toLowerCase()) || fieldRefItems.some((f) => f.value.toLowerCase() === trimmedInput.toLowerCase()), [
83
+ suggestionItems,
84
+ fieldRefItems,
85
+ trimmedInput
86
+ ]);
87
+ const showCreateRow = trimmedInput.length > 0 && !matchesExistingSuggestion;
88
+ const allItems = useMemo(() => {
89
+ const list = [];
90
+ for (const f of fieldRefItems) list.push(f);
91
+ for (const s of suggestionItems) list.push(s);
92
+ if (showCreateRow) list.push({
93
+ value: trimmedInput,
94
+ label: `Add "${trimmedInput}"`,
95
+ kind: "create"
96
+ });
97
+ return list;
98
+ }, [
99
+ fieldRefItems,
100
+ suggestionItems,
101
+ showCreateRow,
102
+ trimmedInput
103
+ ]);
104
+ const atMax = maxItems !== void 0 && items.length >= maxItems;
105
+ const idsRef = useRef([]);
106
+ if (idsRef.current.length !== items.length) if (idsRef.current.length < items.length) idsRef.current = [...idsRef.current, ...Array.from({ length: items.length - idsRef.current.length }, () => crypto.randomUUID())];
107
+ else idsRef.current = idsRef.current.slice(0, items.length);
108
+ const chipIds = idsRef.current;
109
+ const sortSensors = useSensors(useSensor(PointerSensor, { activationConstraint: { distance: 4 } }), useSensor(KeyboardSensor));
110
+ const handleDragEnd = (event) => {
111
+ const { active, over } = event;
112
+ if (!over || active.id === over.id) return;
113
+ const from = chipIds.indexOf(String(active.id));
114
+ const to = chipIds.indexOf(String(over.id));
115
+ if (from === -1 || to === -1) return;
116
+ const nextItems = [...items];
117
+ const [movedValue] = nextItems.splice(from, 1);
118
+ nextItems.splice(to, 0, movedValue);
119
+ const nextIds = [...chipIds];
120
+ const [movedId] = nextIds.splice(from, 1);
121
+ nextIds.splice(to, 0, movedId);
122
+ idsRef.current = nextIds;
123
+ setItems(nextItems);
124
+ };
125
+ const removeAt = (index) => {
126
+ idsRef.current = idsRef.current.filter((_, i) => i !== index);
127
+ setItems(items.filter((_, i) => i !== index));
128
+ };
129
+ const appendValue = (value) => {
130
+ if (atMax || !value) return;
131
+ idsRef.current = [...idsRef.current, crypto.randomUUID()];
132
+ setItems([...items, value]);
133
+ };
134
+ const clearInput = () => {
135
+ setInput("");
136
+ if (isAsync) debouncedSetQuery("");
137
+ };
138
+ const anchor = useComboboxAnchor();
139
+ return /* @__PURE__ */ jsx("div", {
140
+ "data-p0": "input",
141
+ className: "pz:flex pz:flex-col pz:gap-1",
142
+ children: /* @__PURE__ */ jsxs(Combobox, {
143
+ multiple: true,
144
+ items: allItems,
145
+ filter: null,
146
+ open,
147
+ onOpenChange: setOpen,
148
+ value: [],
149
+ onValueChange: (next) => {
150
+ if (!Array.isArray(next) || next.length === 0) return;
151
+ const last = next[next.length - 1];
152
+ appendValue(last.value);
153
+ clearInput();
154
+ },
155
+ isItemEqualToValue: (a, b) => a.value === b.value,
156
+ itemToStringLabel: (item) => item.label,
157
+ itemToStringValue: (item) => item.value,
158
+ inputValue: input,
159
+ onInputValueChange: (v) => {
160
+ setInput(v);
161
+ if (isAsync) debouncedSetQuery(v);
162
+ },
163
+ children: [/* @__PURE__ */ jsxs(ComboboxChips, {
164
+ "aria-invalid": !!field.error || void 0,
165
+ ref: anchor,
166
+ children: [
167
+ /* @__PURE__ */ jsx(DndContext, {
168
+ sensors: sortSensors,
169
+ collisionDetection: closestCenter,
170
+ onDragEnd: handleDragEnd,
171
+ children: /* @__PURE__ */ jsx(SortableContext, {
172
+ items: chipIds,
173
+ strategy: horizontalListSortingStrategy,
174
+ children: items.map((raw, index) => {
175
+ const parsed = parseChip(raw);
176
+ return /* @__PURE__ */ jsx(ChipPill, {
177
+ id: chipIds[index],
178
+ parsed,
179
+ onRemove: () => removeAt(index)
180
+ }, chipIds[index]);
181
+ })
182
+ })
183
+ }),
184
+ /* @__PURE__ */ jsx(ComboboxChipsInput, {
185
+ placeholder: items.length === 0 ? placeholder : void 0,
186
+ "aria-invalid": !!field.error || void 0,
187
+ onKeyDown: (e) => {
188
+ if (e.key === "Backspace" && input.length === 0) {
189
+ if (items.length === 0) return;
190
+ e.preventDefault();
191
+ removeAt(items.length - 1);
192
+ return;
193
+ }
194
+ if (e.key !== "Enter" || e.nativeEvent.isComposing) return;
195
+ if (trimmedInput.length === 0) return;
196
+ e.preventDefault();
197
+ e.stopPropagation();
198
+ if (atMax) return;
199
+ const exactSuggestion = suggestionItems.find((o) => o.value.toLowerCase() === trimmedInput.toLowerCase());
200
+ const exactField = fieldRefItems.find((f) => f.label.toLowerCase() === trimmedInput.toLowerCase());
201
+ appendValue(exactSuggestion?.value ?? exactField?.value ?? trimmedInput);
202
+ clearInput();
203
+ }
204
+ }),
205
+ /* @__PURE__ */ jsx(ComboboxTrigger, { className: "pz:ml-auto pz:bg-transparent pz:hover:bg-transparent" })
206
+ ]
207
+ }), /* @__PURE__ */ jsxs(ComboboxContent, {
208
+ anchor,
209
+ children: [
210
+ loading && allItems.length > 0 && /* @__PURE__ */ jsx("span", {
211
+ "aria-label": "Loading",
212
+ className: "pz:absolute pz:right-2 pz:top-2 pz:z-10 pz:inline-block pz:h-3 pz:w-3 pz:animate-spin pz:rounded-full pz:border-2 pz:border-muted-foreground/30 pz:border-t-muted-foreground"
213
+ }),
214
+ loading && allItems.length === 0 && /* @__PURE__ */ jsx("div", {
215
+ role: "status",
216
+ "aria-label": "Loading",
217
+ className: "pz:flex pz:items-center pz:justify-center pz:py-6",
218
+ children: /* @__PURE__ */ jsx("span", { className: "pz:inline-block pz:h-5 pz:w-5 pz:animate-spin pz:rounded-full pz:border-2 pz:border-muted-foreground/30 pz:border-t-muted-foreground" })
219
+ }),
220
+ /* @__PURE__ */ jsxs(ComboboxList, {
221
+ className: cn(loading && allItems.length > 0 && "pz:opacity-50 pz:transition-opacity pz:pointer-events-none"),
222
+ children: [
223
+ atMax && /* @__PURE__ */ jsxs("div", {
224
+ className: "pz:px-2 pz:py-1.5 pz:text-xs pz:text-muted-foreground",
225
+ children: [
226
+ "Maximum ",
227
+ maxItems,
228
+ " item",
229
+ maxItems === 1 ? "" : "s",
230
+ " reached."
231
+ ]
232
+ }),
233
+ fieldRefItems.length > 0 && /* @__PURE__ */ jsxs(ComboboxGroup, { children: [/* @__PURE__ */ jsx(ComboboxLabel, { children: "Field references" }), fieldRefItems.map((it) => /* @__PURE__ */ jsx(ComboboxItem, {
234
+ value: it,
235
+ disabled: atMax,
236
+ children: /* @__PURE__ */ jsx("span", {
237
+ className: "pz:inline-flex pz:items-center pz:rounded-sm pz:bg-sky-100 pz:px-1 pz:text-sky-900",
238
+ children: it.label
239
+ })
240
+ }, `field:${it.value}`))] }),
241
+ suggestionItems.length > 0 && /* @__PURE__ */ jsxs(ComboboxGroup, { children: [/* @__PURE__ */ jsx(ComboboxLabel, { children: "Suggestions" }), suggestionItems.map((it) => /* @__PURE__ */ jsxs(ComboboxItem, {
242
+ value: it,
243
+ disabled: atMax,
244
+ children: [
245
+ it.widgets && /* @__PURE__ */ jsx(WidgetStrip, {
246
+ widgets: pickLeadingWidgets(it.widgets),
247
+ size: 14
248
+ }),
249
+ /* @__PURE__ */ jsx("span", {
250
+ className: "pz:flex-1 pz:truncate",
251
+ children: it.label
252
+ }),
253
+ it.widgets?.field_type && /* @__PURE__ */ jsx(FieldTypeBadge, {
254
+ type: it.widgets.field_type.type,
255
+ format: it.widgets.field_type.format
256
+ })
257
+ ]
258
+ }, `text:${it.value}`))] }),
259
+ showCreateRow && /* @__PURE__ */ jsx(ComboboxItem, {
260
+ value: {
261
+ value: trimmedInput,
262
+ label: `Add "${trimmedInput}"`,
263
+ kind: "create"
264
+ },
265
+ className: "pz:italic",
266
+ disabled: atMax,
267
+ children: `Add "${trimmedInput}"`
268
+ }, `__create__:${trimmedInput}`),
269
+ !loading && allItems.length === 0 && /* @__PURE__ */ jsx(ComboboxEmpty, { children: trimmedInput.length > 0 ? "No matches" : "Type to add a role" })
270
+ ]
271
+ })
272
+ ]
273
+ })]
274
+ })
275
+ });
276
+ }
277
+ function pickLeadingWidgets(widgets) {
278
+ const { field_type: _ignored, ...rest } = widgets;
279
+ return rest;
280
+ }
281
+ function ChipPill({ id, parsed, onRemove }) {
282
+ const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({ id });
283
+ const style = {
284
+ transform: transform ? `translate3d(${Math.round(transform.x)}px, ${Math.round(transform.y)}px, 0)` : void 0,
285
+ transition,
286
+ opacity: isDragging ? .6 : 1
287
+ };
288
+ const label = parsed.kind === "field" ? parsed.fieldName : parsed.text;
289
+ return /* @__PURE__ */ jsx(ChipShell, {
290
+ setNodeRef,
291
+ style,
292
+ attributes,
293
+ listeners,
294
+ kind: parsed.kind,
295
+ onRemove,
296
+ children: /* @__PURE__ */ jsx("span", {
297
+ className: "pz:px-1",
298
+ children: label || /* @__PURE__ */ jsx("span", {
299
+ className: "pz:text-muted-foreground",
300
+ children: "empty"
301
+ })
302
+ })
303
+ });
304
+ }
305
+ function ChipShell({ setNodeRef, style, attributes, listeners, kind, onRemove, children }) {
306
+ return /* @__PURE__ */ jsxs("span", {
307
+ ref: setNodeRef,
308
+ style,
309
+ className: cn(kind === "field" ? FIELD_CHIP_CLASS : TEXT_CHIP_CLASS),
310
+ "data-chip-kind": kind,
311
+ ...attributes,
312
+ children: [
313
+ /* @__PURE__ */ jsx("span", {
314
+ role: "button",
315
+ tabIndex: -1,
316
+ "aria-label": "Drag to reorder",
317
+ className: "pz:flex pz:items-center pz:justify-center pz:cursor-grab pz:text-muted-foreground pz:hover:text-foreground pz:touch-none",
318
+ ...listeners,
319
+ children: /* @__PURE__ */ jsx(IconGripVertical, {
320
+ width: 12,
321
+ height: 12
322
+ })
323
+ }),
324
+ children,
325
+ /* @__PURE__ */ jsx(Button, {
326
+ type: "button",
327
+ variant: "ghost",
328
+ size: "icon-xs",
329
+ className: "pz:opacity-50 pz:hover:opacity-100",
330
+ onClick: (e) => {
331
+ e.stopPropagation();
332
+ onRemove();
333
+ },
334
+ "aria-label": "Remove",
335
+ children: /* @__PURE__ */ jsx(XIcon, { className: "pz:pointer-events-none" })
336
+ })
337
+ ]
338
+ });
339
+ }
340
+
341
+ //#endregion
342
+ export { TaggedOrderedMultiCreateInputAdapter };
343
+ //# sourceMappingURL=tagged-ordered-multi-create-input.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tagged-ordered-multi-create-input.mjs","names":[],"sources":["../../../../src/components/defaults/adapters/tagged-ordered-multi-create-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 { horizontalListSortingStrategy, SortableContext, useSortable } from \"@dnd-kit/sortable\";\nimport type { PipesFieldDefinitionWithName, WidgetsByKind } from \"@pipe0/base\";\nimport { XIcon } from \"lucide-react\";\nimport { type CSSProperties, type ReactNode, useEffect, useId, useMemo, useRef, useState } from \"react\";\nimport useSWR from \"swr\";\nimport { useDebouncedFn } from \"../../../hooks/use-debounced-fn.js\";\nimport { cn } from \"../../../lib/utils.js\";\nimport type { FieldHandle } from \"../../../types/field-handle.js\";\nimport { FieldTypeBadge } from \"../../../widgets/field-type-badge.js\";\nimport { WidgetStrip } from \"../../../widgets/widget-strip.js\";\nimport { IconGripVertical } from \"../../internal/icons.js\";\nimport { filterOptions, type PayloadOption } from \"../../internal/multi-select-popover-trigger.js\";\nimport { Button } from \"../../ui/button.js\";\nimport {\n Combobox,\n ComboboxChips,\n ComboboxChipsInput,\n ComboboxContent,\n ComboboxEmpty,\n ComboboxGroup,\n ComboboxItem,\n ComboboxLabel,\n ComboboxList,\n ComboboxTrigger,\n useComboboxAnchor,\n} from \"../../ui/combobox.js\";\n\n/**\n * Detects whether a raw value is a single, exclusive Liquid field reference\n * (e.g. `\"{{ company_domain }}\"` or `\"{{ field | filter }}\"`). Mixed content\n * such as `\"Head of {{ company }}\"` returns false and is treated as text.\n */\nconst PURE_TAG_RE =\n /^\\s*\\{\\{\\s*([a-zA-Z_][a-zA-Z0-9_.]*)(?:\\s*\\|\\s*[^}]+)?\\s*\\}\\}\\s*$/;\n\ntype ParsedChip =\n | { kind: \"field\"; fieldName: string; raw: string }\n | { kind: \"text\"; text: string; raw: string };\n\nfunction parseChip(raw: string): ParsedChip {\n const m = raw.match(PURE_TAG_RE);\n if (m) return { kind: \"field\", fieldName: m[1], raw };\n return { kind: \"text\", text: raw, raw };\n}\n\n/**\n * Sky-blue pill matching `TagChipDecoration`'s field chip styling so a\n * field-reference chip outside tiptap reads identically to one inside\n * `LiquidEditor`.\n */\nconst FIELD_CHIP_CLASS =\n \"pz:flex pz:h-[calc(--spacing(5.25))] pz:w-fit pz:items-center pz:gap-1 pz:rounded-sm pz:bg-sky-100 pz:pl-0.5 pz:pr-0 pz:text-xs pz:font-medium pz:whitespace-nowrap pz:text-sky-900\";\n\nconst TEXT_CHIP_CLASS =\n \"pz:flex pz:h-[calc(--spacing(5.25))] pz:w-fit pz:items-center pz:gap-1 pz:rounded-sm pz:bg-muted pz:pl-0.5 pz:pr-0 pz:text-xs pz:font-medium pz:whitespace-nowrap pz:text-foreground\";\n\n/** Drop target for an item carried by the Combobox value channel. */\ntype Item = {\n /** Canonical value to store in the field — text as-is, or `{{ fieldName }}`. */\n value: string;\n /** Display label in the dropdown. */\n label: string;\n kind: \"field\" | \"text\" | \"create\";\n widgets?: WidgetsByKind;\n};\n\nexport function TaggedOrderedMultiCreateInputAdapter(\n field: FieldHandle<\"tagged_ordered_multi_create_input\">,\n) {\n const { items, setItems, options, loadOptions, inputFields, meta } = field;\n const maxItems = meta.maxItems;\n const placeholder = meta.placeholder;\n\n const [input, setInput] = useState(\"\");\n const [debouncedQuery, setDebouncedQuery] = useState(\"\");\n const [open, setOpen] = useState(false);\n\n const isAsync = typeof loadOptions === \"function\";\n const debouncedSetQuery = useDebouncedFn((q: string) => setDebouncedQuery(q), 300);\n\n // Async suggestions — same SWR pattern as `SuggestCombobox`.\n const instanceId = useId();\n const swrKey: readonly [string, string] | null =\n loadOptions && (open || debouncedQuery !== \"\") ? [instanceId, debouncedQuery] : null;\n const {\n data: asyncResults = null,\n isLoading: swrIsLoading,\n isValidating: swrIsValidating,\n } = useSWR<PayloadOption[], Error, readonly [string, string] | null>(\n swrKey,\n async ([, q]) => {\n if (!loadOptions) return [];\n const opts = await loadOptions(q);\n return opts.filter((o) => !!o.value);\n },\n { keepPreviousData: true },\n );\n const loading = swrIsLoading || swrIsValidating;\n\n const trimmedInput = input.trim();\n\n const fieldRefItems = useMemo<Item[]>(() => {\n if (!inputFields?.length) return [];\n const q = trimmedInput.toLowerCase();\n return inputFields\n .filter((f) => !q || f.resolvedName.toLowerCase().includes(q))\n .map<Item>((f) => ({\n value: `{{ ${f.resolvedName} }}`,\n label: f.resolvedName,\n kind: \"field\",\n }));\n }, [inputFields, trimmedInput]);\n\n const suggestionItems = useMemo<Item[]>(() => {\n const source: PayloadOption[] = isAsync ? (asyncResults ?? []) : (options ?? []);\n const ranked: PayloadOption[] = isAsync ? source : filterOptions(source, input);\n return ranked.map<Item>((o) => ({\n value: o.value,\n label: o.label,\n kind: \"text\",\n widgets: o.widgets,\n }));\n }, [isAsync, asyncResults, options, input]);\n\n const matchesExistingSuggestion = useMemo(\n () =>\n suggestionItems.some((o) => o.value.toLowerCase() === trimmedInput.toLowerCase()) ||\n fieldRefItems.some((f) => f.value.toLowerCase() === trimmedInput.toLowerCase()),\n [suggestionItems, fieldRefItems, trimmedInput],\n );\n\n const showCreateRow = trimmedInput.length > 0 && !matchesExistingSuggestion;\n\n // Flat items list — fed to base-ui as the universe of pickable items so its\n // keyboard navigation has a single ordering to work with. The visual\n // grouping is done by `ComboboxGroup` in the render below; base-ui ranges\n // over `items` linearly and matches by reference.\n const allItems = useMemo<Item[]>(() => {\n const list: Item[] = [];\n for (const f of fieldRefItems) list.push(f);\n for (const s of suggestionItems) list.push(s);\n if (showCreateRow) {\n list.push({\n value: trimmedInput,\n label: `Add \"${trimmedInput}\"`,\n kind: \"create\",\n });\n }\n return list;\n }, [fieldRefItems, suggestionItems, showCreateRow, trimmedInput]);\n\n const atMax = maxItems !== undefined && items.length >= maxItems;\n\n // Stable per-position ids so `@dnd-kit` keys survive even when two chips\n // share the same raw string (uncommon, but allowed — the user could insert\n // the same field reference twice in a waterfall).\n const idsRef = useRef<string[]>([]);\n if (idsRef.current.length !== items.length) {\n if (idsRef.current.length < items.length) {\n idsRef.current = [\n ...idsRef.current,\n ...Array.from(\n { length: items.length - idsRef.current.length },\n () => crypto.randomUUID(),\n ),\n ];\n } else {\n idsRef.current = idsRef.current.slice(0, items.length);\n }\n }\n const chipIds = idsRef.current;\n\n const sortSensors = 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 = chipIds.indexOf(String(active.id));\n const to = chipIds.indexOf(String(over.id));\n if (from === -1 || to === -1) return;\n const nextItems = [...items];\n const [movedValue] = nextItems.splice(from, 1);\n nextItems.splice(to, 0, movedValue);\n const nextIds = [...chipIds];\n const [movedId] = nextIds.splice(from, 1);\n nextIds.splice(to, 0, movedId);\n idsRef.current = nextIds;\n setItems(nextItems);\n };\n\n const removeAt = (index: number) => {\n idsRef.current = idsRef.current.filter((_, i) => i !== index);\n setItems(items.filter((_, i) => i !== index));\n };\n\n const appendValue = (value: string) => {\n if (atMax || !value) return;\n idsRef.current = [...idsRef.current, crypto.randomUUID()];\n setItems([...items, value]);\n };\n\n const clearInput = () => {\n setInput(\"\");\n if (isAsync) debouncedSetQuery(\"\");\n };\n\n const anchor = useComboboxAnchor();\n\n return (\n <div data-p0=\"input\" className=\"pz:flex pz:flex-col pz:gap-1\">\n <Combobox<Item, true>\n multiple\n items={allItems}\n filter={null}\n open={open}\n onOpenChange={setOpen}\n // Chips are rendered manually so base-ui doesn't manage them — keep\n // `value` empty and capture picks via `onValueChange`. Same trick as\n // `IncludeExcludeCombobox`.\n value={[] as Item[]}\n onValueChange={(next) => {\n if (!Array.isArray(next) || next.length === 0) return;\n const last = next[next.length - 1] as Item;\n appendValue(last.value);\n clearInput();\n }}\n isItemEqualToValue={(a, b) => (a as Item).value === (b as Item).value}\n itemToStringLabel={(item) => (item as Item).label}\n itemToStringValue={(item) => (item as Item).value}\n inputValue={input}\n onInputValueChange={(v) => {\n setInput(v);\n if (isAsync) debouncedSetQuery(v);\n }}\n >\n <ComboboxChips aria-invalid={!!field.error || undefined} ref={anchor}>\n <DndContext\n sensors={sortSensors}\n collisionDetection={closestCenter}\n onDragEnd={handleDragEnd}\n >\n <SortableContext items={chipIds} strategy={horizontalListSortingStrategy}>\n {items.map((raw, index) => {\n const parsed = parseChip(raw);\n return (\n <ChipPill\n key={chipIds[index]}\n id={chipIds[index]}\n parsed={parsed}\n onRemove={() => removeAt(index)}\n />\n );\n })}\n </SortableContext>\n </DndContext>\n <ComboboxChipsInput\n placeholder={items.length === 0 ? placeholder : undefined}\n aria-invalid={!!field.error || undefined}\n onKeyDown={(e) => {\n if (e.key === \"Backspace\" && input.length === 0) {\n if (items.length === 0) return;\n e.preventDefault();\n removeAt(items.length - 1);\n return;\n }\n if (e.key !== \"Enter\" || e.nativeEvent.isComposing) return;\n if (trimmedInput.length === 0) return;\n e.preventDefault();\n e.stopPropagation();\n if (atMax) return;\n // Prefer exact suggestion match, then exact field match, else\n // create a text entry.\n const exactSuggestion = suggestionItems.find(\n (o) => o.value.toLowerCase() === trimmedInput.toLowerCase(),\n );\n const exactField = fieldRefItems.find(\n (f) => f.label.toLowerCase() === trimmedInput.toLowerCase(),\n );\n const toAdd = exactSuggestion?.value ?? exactField?.value ?? trimmedInput;\n appendValue(toAdd);\n clearInput();\n }}\n />\n <ComboboxTrigger className=\"pz:ml-auto pz:bg-transparent pz:hover:bg-transparent\" />\n </ComboboxChips>\n <ComboboxContent anchor={anchor}>\n {loading && allItems.length > 0 && (\n <span\n aria-label=\"Loading\"\n className=\"pz:absolute pz:right-2 pz:top-2 pz:z-10 pz:inline-block pz:h-3 pz:w-3 pz:animate-spin pz:rounded-full pz:border-2 pz:border-muted-foreground/30 pz:border-t-muted-foreground\"\n />\n )}\n {loading && allItems.length === 0 && (\n <div\n role=\"status\"\n aria-label=\"Loading\"\n className=\"pz:flex pz:items-center pz:justify-center pz:py-6\"\n >\n <span className=\"pz:inline-block pz:h-5 pz:w-5 pz:animate-spin pz:rounded-full pz:border-2 pz:border-muted-foreground/30 pz:border-t-muted-foreground\" />\n </div>\n )}\n <ComboboxList\n className={cn(\n loading &&\n allItems.length > 0 &&\n \"pz:opacity-50 pz:transition-opacity pz:pointer-events-none\",\n )}\n >\n {atMax && (\n <div className=\"pz:px-2 pz:py-1.5 pz:text-xs pz:text-muted-foreground\">\n Maximum {maxItems} item{maxItems === 1 ? \"\" : \"s\"} reached.\n </div>\n )}\n\n {fieldRefItems.length > 0 && (\n <ComboboxGroup>\n <ComboboxLabel>Field references</ComboboxLabel>\n {fieldRefItems.map((it) => (\n <ComboboxItem\n key={`field:${it.value}`}\n value={it}\n disabled={atMax}\n >\n <span className=\"pz:inline-flex pz:items-center pz:rounded-sm pz:bg-sky-100 pz:px-1 pz:text-sky-900\">\n {it.label}\n </span>\n </ComboboxItem>\n ))}\n </ComboboxGroup>\n )}\n\n {suggestionItems.length > 0 && (\n <ComboboxGroup>\n <ComboboxLabel>Suggestions</ComboboxLabel>\n {suggestionItems.map((it) => (\n <ComboboxItem\n key={`text:${it.value}`}\n value={it}\n disabled={atMax}\n >\n {it.widgets && (\n <WidgetStrip widgets={pickLeadingWidgets(it.widgets)} size={14} />\n )}\n <span className=\"pz:flex-1 pz:truncate\">{it.label}</span>\n {it.widgets?.field_type && (\n <FieldTypeBadge\n type={it.widgets.field_type.type}\n format={it.widgets.field_type.format}\n />\n )}\n </ComboboxItem>\n ))}\n </ComboboxGroup>\n )}\n\n {showCreateRow && (\n <ComboboxItem\n key={`__create__:${trimmedInput}`}\n value={{ value: trimmedInput, label: `Add \"${trimmedInput}\"`, kind: \"create\" }}\n className=\"pz:italic\"\n disabled={atMax}\n >\n {`Add \"${trimmedInput}\"`}\n </ComboboxItem>\n )}\n\n {!loading && allItems.length === 0 && (\n <ComboboxEmpty>\n {trimmedInput.length > 0 ? \"No matches\" : \"Type to add a role\"}\n </ComboboxEmpty>\n )}\n </ComboboxList>\n </ComboboxContent>\n </Combobox>\n </div>\n );\n}\n\nfunction pickLeadingWidgets(widgets: WidgetsByKind): WidgetsByKind {\n const { field_type: _ignored, ...rest } = widgets;\n return rest;\n}\n\nfunction ChipPill({\n id,\n parsed,\n onRemove,\n}: {\n id: string;\n parsed: ParsedChip;\n onRemove: () => void;\n}) {\n const { attributes, listeners, setNodeRef, transform, transition, isDragging } = useSortable({\n id,\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 const isField = parsed.kind === \"field\";\n const label = isField ? parsed.fieldName : parsed.text;\n return (\n <ChipShell\n setNodeRef={setNodeRef}\n style={style}\n attributes={attributes}\n listeners={listeners}\n kind={parsed.kind}\n onRemove={onRemove}\n >\n <span className=\"pz:px-1\">{label || <span className=\"pz:text-muted-foreground\">empty</span>}</span>\n </ChipShell>\n );\n}\n\nfunction ChipShell({\n setNodeRef,\n style,\n attributes,\n listeners,\n kind,\n onRemove,\n children,\n}: {\n setNodeRef: (n: HTMLElement | null) => void;\n style: CSSProperties;\n // biome-ignore lint/suspicious/noExplicitAny: dnd-kit attribute/listener shape\n attributes: any;\n // biome-ignore lint/suspicious/noExplicitAny: dnd-kit attribute/listener shape\n listeners: any;\n kind: ParsedChip[\"kind\"];\n onRemove: () => void;\n children: ReactNode;\n}) {\n return (\n <span\n ref={setNodeRef}\n style={style}\n className={cn(kind === \"field\" ? FIELD_CHIP_CLASS : TEXT_CHIP_CLASS)}\n data-chip-kind={kind}\n {...attributes}\n >\n <span\n role=\"button\"\n tabIndex={-1}\n aria-label=\"Drag to reorder\"\n className=\"pz:flex pz:items-center pz:justify-center pz:cursor-grab pz:text-muted-foreground pz:hover:text-foreground pz:touch-none\"\n {...listeners}\n >\n <IconGripVertical width={12} height={12} />\n </span>\n {children}\n <Button\n type=\"button\"\n variant=\"ghost\"\n size=\"icon-xs\"\n className=\"pz:opacity-50 pz:hover:opacity-100\"\n onClick={(e) => {\n e.stopPropagation();\n onRemove();\n }}\n aria-label=\"Remove\"\n >\n <XIcon className=\"pz:pointer-events-none\" />\n </Button>\n </span>\n );\n}\n"],"mappings":"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"}
@@ -56,6 +56,20 @@ function ComboboxItem({ className, children, ...props }) {
56
56
  })]
57
57
  });
58
58
  }
59
+ function ComboboxGroup({ className, ...props }) {
60
+ return /* @__PURE__ */ jsx(Combobox.Group, {
61
+ "data-slot": "combobox-group",
62
+ className: cn(className),
63
+ ...props
64
+ });
65
+ }
66
+ function ComboboxLabel({ className, ...props }) {
67
+ return /* @__PURE__ */ jsx(Combobox.GroupLabel, {
68
+ "data-slot": "combobox-label",
69
+ className: cn("pz:px-2 pz:py-1.5 pz:text-xs pz:text-muted-foreground", className),
70
+ ...props
71
+ });
72
+ }
59
73
  function ComboboxEmpty({ className, ...props }) {
60
74
  return /* @__PURE__ */ jsx(Combobox.Empty, {
61
75
  "data-slot": "combobox-empty",
@@ -98,5 +112,5 @@ function useComboboxAnchor() {
98
112
  }
99
113
 
100
114
  //#endregion
101
- export { Combobox$1 as Combobox, ComboboxChip, ComboboxChips, ComboboxChipsInput, ComboboxContent, ComboboxEmpty, ComboboxItem, ComboboxList, ComboboxTrigger, useComboboxAnchor };
115
+ export { Combobox$1 as Combobox, ComboboxChip, ComboboxChips, ComboboxChipsInput, ComboboxContent, ComboboxEmpty, ComboboxGroup, ComboboxItem, ComboboxLabel, ComboboxList, ComboboxTrigger, useComboboxAnchor };
102
116
  //# sourceMappingURL=combobox.mjs.map