@petrarca/sonnet-ui 0.4.0 → 0.4.1

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/dist/index.js CHANGED
@@ -3007,14 +3007,222 @@ function PaginationFooter({
3007
3007
  ] });
3008
3008
  }
3009
3009
 
3010
+ // src/PropertyList/PropertyList.tsx
3011
+ import { copyTextToClipboard } from "@petrarca/sonnet-core";
3012
+
3013
+ // src/PropertyList/PropertyValue.tsx
3014
+ import { useState as useState3 } from "react";
3015
+ import { JSONTree } from "react-json-tree";
3016
+ import { jsx as jsx29, jsxs as jsxs9 } from "react/jsx-runtime";
3017
+ var DEFAULT_CLAMP_CHARS = 180;
3018
+ var tokenTheme = {
3019
+ scheme: "sonnet",
3020
+ base00: "transparent",
3021
+ base01: "hsl(var(--muted))",
3022
+ base02: "hsl(var(--border))",
3023
+ base03: "hsl(var(--muted-foreground))",
3024
+ base04: "hsl(var(--muted-foreground))",
3025
+ base05: "hsl(var(--foreground))",
3026
+ base06: "hsl(var(--foreground))",
3027
+ base07: "hsl(var(--foreground))",
3028
+ base08: "hsl(var(--destructive))",
3029
+ base09: "hsl(var(--primary))",
3030
+ base0A: "hsl(var(--primary))",
3031
+ base0B: "hsl(var(--primary))",
3032
+ base0C: "hsl(var(--primary))",
3033
+ base0D: "hsl(var(--primary))",
3034
+ base0E: "hsl(var(--primary))",
3035
+ base0F: "hsl(var(--muted-foreground))"
3036
+ };
3037
+ function isObjectLike(v) {
3038
+ return typeof v === "object" && v !== null;
3039
+ }
3040
+ function JsonValue({ value }) {
3041
+ const [open, setOpen] = useState3(false);
3042
+ const summary = Array.isArray(value) ? `[${value.length} item${value.length === 1 ? "" : "s"}]` : `{${Object.keys(value).length} key${Object.keys(value).length === 1 ? "" : "s"}}`;
3043
+ if (!open) {
3044
+ return /* @__PURE__ */ jsxs9(
3045
+ "button",
3046
+ {
3047
+ type: "button",
3048
+ onClick: (e) => {
3049
+ e.stopPropagation();
3050
+ setOpen(true);
3051
+ },
3052
+ className: "text-sm font-mono text-muted-foreground hover:text-foreground",
3053
+ children: [
3054
+ summary,
3055
+ " ",
3056
+ /* @__PURE__ */ jsx29("span", { className: "text-xs", children: "\u2014 show" })
3057
+ ]
3058
+ }
3059
+ );
3060
+ }
3061
+ return /* @__PURE__ */ jsxs9("div", { className: "text-xs font-mono", children: [
3062
+ /* @__PURE__ */ jsx29(
3063
+ "button",
3064
+ {
3065
+ type: "button",
3066
+ onClick: (e) => {
3067
+ e.stopPropagation();
3068
+ setOpen(false);
3069
+ },
3070
+ className: "mb-1 text-xs text-muted-foreground hover:text-foreground",
3071
+ children: "hide"
3072
+ }
3073
+ ),
3074
+ /* @__PURE__ */ jsx29("div", { className: "max-h-64 overflow-auto rounded border border-border bg-muted/30 px-2 py-1", children: /* @__PURE__ */ jsx29(
3075
+ JSONTree,
3076
+ {
3077
+ data: value,
3078
+ theme: tokenTheme,
3079
+ invertTheme: false,
3080
+ shouldExpandNodeInitially: () => true,
3081
+ hideRoot: true
3082
+ }
3083
+ ) })
3084
+ ] });
3085
+ }
3086
+ function LongTextValue({ text }) {
3087
+ const [open, setOpen] = useState3(false);
3088
+ if (!open) {
3089
+ return /* @__PURE__ */ jsxs9("span", { className: "break-words", children: [
3090
+ /* @__PURE__ */ jsx29("span", { className: "line-clamp-3 align-bottom", children: text }),
3091
+ /* @__PURE__ */ jsx29(
3092
+ "button",
3093
+ {
3094
+ type: "button",
3095
+ onClick: (e) => {
3096
+ e.stopPropagation();
3097
+ setOpen(true);
3098
+ },
3099
+ className: "text-xs text-muted-foreground hover:text-foreground",
3100
+ children: "Show more"
3101
+ }
3102
+ )
3103
+ ] });
3104
+ }
3105
+ return /* @__PURE__ */ jsxs9("span", { className: "break-words", children: [
3106
+ /* @__PURE__ */ jsx29("span", { className: "block max-h-64 overflow-auto whitespace-pre-wrap rounded border border-border bg-muted/30 px-2 py-1", children: text }),
3107
+ /* @__PURE__ */ jsx29(
3108
+ "button",
3109
+ {
3110
+ type: "button",
3111
+ onClick: (e) => {
3112
+ e.stopPropagation();
3113
+ setOpen(false);
3114
+ },
3115
+ className: "text-xs text-muted-foreground hover:text-foreground",
3116
+ children: "Show less"
3117
+ }
3118
+ )
3119
+ ] });
3120
+ }
3121
+ function renderFromSchema(value, schema, className) {
3122
+ const cellName = schema["x-ui-cell"] ?? inferCellRenderer(schema.type, schema.format);
3123
+ if (cellName === "json") {
3124
+ const parsed = typeof value === "string" ? safeParse(value) : value;
3125
+ return isObjectLike(parsed) ? /* @__PURE__ */ jsx29(JsonValue, { value: parsed }) : null;
3126
+ }
3127
+ if (cellName && cellName !== "text") {
3128
+ const Renderer = CELL_RENDERERS[cellName];
3129
+ if (Renderer) {
3130
+ return /* @__PURE__ */ jsx29("span", { className, children: /* @__PURE__ */ jsx29(
3131
+ Renderer,
3132
+ {
3133
+ value,
3134
+ row: {},
3135
+ options: schema["x-ui-cell-options"] ?? {}
3136
+ }
3137
+ ) });
3138
+ }
3139
+ }
3140
+ return null;
3141
+ }
3142
+ function renderObjectLike(value, className) {
3143
+ if (Array.isArray(value) && value.every((v) => !isObjectLike(v))) {
3144
+ return /* @__PURE__ */ jsx29("span", { className: `break-words ${className ?? ""}`, children: value.map(String).join(", ") });
3145
+ }
3146
+ return /* @__PURE__ */ jsx29(JsonValue, { value });
3147
+ }
3148
+ function renderString(value, className, clampChars) {
3149
+ if (typeof value === "boolean") {
3150
+ return /* @__PURE__ */ jsx29("span", { className, children: value ? "true" : "false" });
3151
+ }
3152
+ const str = String(value);
3153
+ if (str.length > clampChars || str.includes("\n")) {
3154
+ return /* @__PURE__ */ jsx29("span", { className, children: /* @__PURE__ */ jsx29(LongTextValue, { text: str }) });
3155
+ }
3156
+ return /* @__PURE__ */ jsx29("span", { className: `break-words ${className ?? ""}`, children: str });
3157
+ }
3158
+ function renderFromValue(value, className, clampChars) {
3159
+ if (value == null) {
3160
+ return /* @__PURE__ */ jsx29("span", { className: `text-muted-foreground ${className ?? ""}`, children: "\u2014" });
3161
+ }
3162
+ if (isObjectLike(value)) return renderObjectLike(value, className);
3163
+ return renderString(value, className, clampChars);
3164
+ }
3165
+ function PropertyValue({
3166
+ value,
3167
+ schema,
3168
+ className,
3169
+ clampChars = DEFAULT_CLAMP_CHARS
3170
+ }) {
3171
+ const fromSchema = schema ? renderFromSchema(value, schema, className) : null;
3172
+ return fromSchema ?? renderFromValue(value, className, clampChars);
3173
+ }
3174
+ function safeParse(s) {
3175
+ try {
3176
+ return JSON.parse(s);
3177
+ } catch {
3178
+ return void 0;
3179
+ }
3180
+ }
3181
+
3182
+ // src/PropertyList/PropertyList.tsx
3183
+ import { jsx as jsx30, jsxs as jsxs10 } from "react/jsx-runtime";
3184
+ function PropertyList({
3185
+ properties,
3186
+ propertySchemas,
3187
+ showHeader = false,
3188
+ copyable = true,
3189
+ emptyLabel = "No properties",
3190
+ className
3191
+ }) {
3192
+ const entries = Object.entries(properties ?? {});
3193
+ if (entries.length === 0) {
3194
+ return /* @__PURE__ */ jsx30("p", { className: "text-sm text-muted-foreground italic", children: emptyLabel });
3195
+ }
3196
+ return /* @__PURE__ */ jsxs10("ul", { className: `list-none ${className ?? ""}`, children: [
3197
+ showHeader && /* @__PURE__ */ jsx30("li", { className: "text-xs font-medium text-muted-foreground uppercase tracking-wide mb-1", children: "Properties" }),
3198
+ entries.map(([key, value]) => /* @__PURE__ */ jsxs10("li", { className: "mb-2 leading-tight", children: [
3199
+ /* @__PURE__ */ jsx30(
3200
+ "p",
3201
+ {
3202
+ className: `text-xs text-muted-foreground uppercase tracking-wide ${copyable ? "cursor-pointer hover:text-foreground" : ""}`,
3203
+ onClick: copyable ? () => copyTextToClipboard(stringForCopy(value)) : void 0,
3204
+ title: copyable ? "Click to copy value" : void 0,
3205
+ children: key
3206
+ }
3207
+ ),
3208
+ /* @__PURE__ */ jsx30("div", { className: "text-sm text-foreground", children: /* @__PURE__ */ jsx30(PropertyValue, { value, schema: propertySchemas?.[key] }) })
3209
+ ] }, key))
3210
+ ] });
3211
+ }
3212
+ function stringForCopy(value) {
3213
+ if (value == null) return "";
3214
+ if (typeof value === "object") return JSON.stringify(value);
3215
+ return String(value);
3216
+ }
3217
+
3010
3218
  // src/EntitySelect/EntitySelect.tsx
3011
- import * as React25 from "react";
3219
+ import * as React26 from "react";
3012
3220
  import { Check as Check4, ChevronsUpDown, Loader2 } from "lucide-react";
3013
3221
  import { cn as cn27 } from "@petrarca/sonnet-core";
3014
3222
  import {
3015
3223
  useEntityOptions
3016
3224
  } from "@petrarca/sonnet-core/hooks";
3017
- import { Fragment as Fragment2, jsx as jsx29, jsxs as jsxs9 } from "react/jsx-runtime";
3225
+ import { Fragment as Fragment2, jsx as jsx31, jsxs as jsxs11 } from "react/jsx-runtime";
3018
3226
  function emptyStateMessage({
3019
3227
  mode,
3020
3228
  search,
@@ -3032,8 +3240,8 @@ function emptyStateMessage({
3032
3240
  return emptyMessage;
3033
3241
  }
3034
3242
  function useHasSearched(submit) {
3035
- const [hasSearched, setHasSearched] = React25.useState(false);
3036
- const wrappedSubmit = React25.useCallback(() => {
3243
+ const [hasSearched, setHasSearched] = React26.useState(false);
3244
+ const wrappedSubmit = React26.useCallback(() => {
3037
3245
  setHasSearched(true);
3038
3246
  submit();
3039
3247
  }, [submit]);
@@ -3056,19 +3264,19 @@ function EntitySelectLabel({
3056
3264
  description
3057
3265
  }) {
3058
3266
  const hasLabel = label !== void 0 && label !== false;
3059
- return /* @__PURE__ */ jsxs9(Fragment2, { children: [
3060
- hasLabel && /* @__PURE__ */ jsxs9(
3267
+ return /* @__PURE__ */ jsxs11(Fragment2, { children: [
3268
+ hasLabel && /* @__PURE__ */ jsxs11(
3061
3269
  "label",
3062
3270
  {
3063
3271
  htmlFor: id,
3064
3272
  className: "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70",
3065
3273
  children: [
3066
3274
  label,
3067
- required && /* @__PURE__ */ jsx29("span", { className: "ml-1 text-destructive", children: "*" })
3275
+ required && /* @__PURE__ */ jsx31("span", { className: "ml-1 text-destructive", children: "*" })
3068
3276
  ]
3069
3277
  }
3070
3278
  ),
3071
- description && /* @__PURE__ */ jsx29("p", { className: "text-sm text-muted-foreground", children: description })
3279
+ description && /* @__PURE__ */ jsx31("p", { className: "text-sm text-muted-foreground", children: description })
3072
3280
  ] });
3073
3281
  }
3074
3282
  function EntitySelectDropdown({
@@ -3085,8 +3293,8 @@ function EntitySelectDropdown({
3085
3293
  value,
3086
3294
  handleSelect
3087
3295
  }) {
3088
- return /* @__PURE__ */ jsxs9(Command, { shouldFilter: false, children: [
3089
- /* @__PURE__ */ jsx29(
3296
+ return /* @__PURE__ */ jsxs11(Command, { shouldFilter: false, children: [
3297
+ /* @__PURE__ */ jsx31(
3090
3298
  CommandInput,
3091
3299
  {
3092
3300
  placeholder: searchPlaceholder,
@@ -3100,8 +3308,8 @@ function EntitySelectDropdown({
3100
3308
  } : void 0
3101
3309
  }
3102
3310
  ),
3103
- /* @__PURE__ */ jsxs9(CommandList, { children: [
3104
- /* @__PURE__ */ jsx29(CommandEmpty, { children: emptyStateMessage({
3311
+ /* @__PURE__ */ jsxs11(CommandList, { children: [
3312
+ /* @__PURE__ */ jsx31(CommandEmpty, { children: emptyStateMessage({
3105
3313
  mode,
3106
3314
  search,
3107
3315
  minChars,
@@ -3109,13 +3317,13 @@ function EntitySelectDropdown({
3109
3317
  hasSearched,
3110
3318
  emptyMessage
3111
3319
  }) }),
3112
- /* @__PURE__ */ jsx29(CommandGroup, { children: options.map((option) => /* @__PURE__ */ jsxs9(
3320
+ /* @__PURE__ */ jsx31(CommandGroup, { children: options.map((option) => /* @__PURE__ */ jsxs11(
3113
3321
  CommandItem,
3114
3322
  {
3115
3323
  value: option.value,
3116
3324
  onSelect: handleSelect,
3117
3325
  children: [
3118
- /* @__PURE__ */ jsx29(
3326
+ /* @__PURE__ */ jsx31(
3119
3327
  Check4,
3120
3328
  {
3121
3329
  className: cn27(
@@ -3155,8 +3363,8 @@ function EntitySelect(props) {
3155
3363
  emptyMessage,
3156
3364
  disabled
3157
3365
  } = resolveEntitySelectDefaults(props);
3158
- const [open, setOpen] = React25.useState(false);
3159
- const [selectedLabel, setSelectedLabel] = React25.useState(null);
3366
+ const [open, setOpen] = React26.useState(false);
3367
+ const [selectedLabel, setSelectedLabel] = React26.useState(null);
3160
3368
  const {
3161
3369
  options,
3162
3370
  isLoading,
@@ -3165,7 +3373,7 @@ function EntitySelect(props) {
3165
3373
  submit: rawSubmit
3166
3374
  } = useEntityOptions({ fetcher, queryKey, mode, minChars });
3167
3375
  const [hasSearched, submit] = useHasSearched(rawSubmit);
3168
- React25.useEffect(() => {
3376
+ React26.useEffect(() => {
3169
3377
  if (!value) {
3170
3378
  setSelectedLabel(null);
3171
3379
  return;
@@ -3175,7 +3383,7 @@ function EntitySelect(props) {
3175
3383
  setSelectedLabel(found.label);
3176
3384
  }
3177
3385
  }, [value, options]);
3178
- const handleSelect = React25.useCallback(
3386
+ const handleSelect = React26.useCallback(
3179
3387
  (selectedValue) => {
3180
3388
  const opt = options.find((o) => o.value === selectedValue);
3181
3389
  if (opt) setSelectedLabel(opt.label);
@@ -3188,7 +3396,7 @@ function EntitySelect(props) {
3188
3396
  },
3189
3397
  [options, value, onChange, onChangeOption, setSearch]
3190
3398
  );
3191
- const handleOpenChange = React25.useCallback(
3399
+ const handleOpenChange = React26.useCallback(
3192
3400
  (newOpen) => {
3193
3401
  setOpen(newOpen);
3194
3402
  if (!newOpen) {
@@ -3198,8 +3406,8 @@ function EntitySelect(props) {
3198
3406
  },
3199
3407
  [onBlur, setSearch]
3200
3408
  );
3201
- return /* @__PURE__ */ jsxs9("div", { className: cn27("space-y-2", className), children: [
3202
- /* @__PURE__ */ jsx29(
3409
+ return /* @__PURE__ */ jsxs11("div", { className: cn27("space-y-2", className), children: [
3410
+ /* @__PURE__ */ jsx31(
3203
3411
  EntitySelectLabel,
3204
3412
  {
3205
3413
  id,
@@ -3208,8 +3416,8 @@ function EntitySelect(props) {
3208
3416
  description
3209
3417
  }
3210
3418
  ),
3211
- /* @__PURE__ */ jsxs9(Popover, { open, onOpenChange: handleOpenChange, children: [
3212
- /* @__PURE__ */ jsx29(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs9(
3419
+ /* @__PURE__ */ jsxs11(Popover, { open, onOpenChange: handleOpenChange, children: [
3420
+ /* @__PURE__ */ jsx31(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs11(
3213
3421
  Button,
3214
3422
  {
3215
3423
  id,
@@ -3223,20 +3431,20 @@ function EntitySelect(props) {
3223
3431
  ),
3224
3432
  disabled,
3225
3433
  children: [
3226
- /* @__PURE__ */ jsx29("span", { className: "truncate", children: selectedLabel ?? placeholder }),
3227
- /* @__PURE__ */ jsxs9("div", { className: "flex items-center gap-1", children: [
3228
- isLoading && /* @__PURE__ */ jsx29(Loader2, { className: "h-4 w-4 animate-spin opacity-50" }),
3229
- /* @__PURE__ */ jsx29(ChevronsUpDown, { className: "h-4 w-4 shrink-0 opacity-50" })
3434
+ /* @__PURE__ */ jsx31("span", { className: "truncate", children: selectedLabel ?? placeholder }),
3435
+ /* @__PURE__ */ jsxs11("div", { className: "flex items-center gap-1", children: [
3436
+ isLoading && /* @__PURE__ */ jsx31(Loader2, { className: "h-4 w-4 animate-spin opacity-50" }),
3437
+ /* @__PURE__ */ jsx31(ChevronsUpDown, { className: "h-4 w-4 shrink-0 opacity-50" })
3230
3438
  ] })
3231
3439
  ]
3232
3440
  }
3233
3441
  ) }),
3234
- /* @__PURE__ */ jsx29(
3442
+ /* @__PURE__ */ jsx31(
3235
3443
  PopoverContent,
3236
3444
  {
3237
3445
  className: "w-[--radix-popover-trigger-width] p-0",
3238
3446
  align: "start",
3239
- children: /* @__PURE__ */ jsx29(
3447
+ children: /* @__PURE__ */ jsx31(
3240
3448
  EntitySelectDropdown,
3241
3449
  {
3242
3450
  searchPlaceholder,
@@ -3256,7 +3464,7 @@ function EntitySelect(props) {
3256
3464
  }
3257
3465
  )
3258
3466
  ] }),
3259
- error && /* @__PURE__ */ jsx29("p", { className: "text-sm font-medium text-destructive", children: error })
3467
+ error && /* @__PURE__ */ jsx31("p", { className: "text-sm font-medium text-destructive", children: error })
3260
3468
  ] });
3261
3469
  }
3262
3470
 
@@ -3279,11 +3487,11 @@ import {
3279
3487
  useImperativeHandle,
3280
3488
  useMemo as useMemo3,
3281
3489
  useRef as useRef5,
3282
- useState as useState4
3490
+ useState as useState5
3283
3491
  } from "react";
3284
3492
  import { ChevronRight as ChevronRight3 } from "lucide-react";
3285
3493
  import { cn as cn28 } from "@petrarca/sonnet-core";
3286
- import { jsx as jsx30, jsxs as jsxs10 } from "react/jsx-runtime";
3494
+ import { jsx as jsx32, jsxs as jsxs12 } from "react/jsx-runtime";
3287
3495
  function flatten(nodes, expandedIds, depth = 0, parentId = null, result = []) {
3288
3496
  for (const node of nodes) {
3289
3497
  result.push({ node, depth, parentId });
@@ -3300,12 +3508,12 @@ function ToggleIcon({
3300
3508
  isExpanded
3301
3509
  }) {
3302
3510
  if (!hasChildren) {
3303
- return /* @__PURE__ */ jsx30("span", { className: "block w-1.5 h-1.5 rounded-full bg-border mx-auto" });
3511
+ return /* @__PURE__ */ jsx32("span", { className: "block w-1.5 h-1.5 rounded-full bg-border mx-auto" });
3304
3512
  }
3305
3513
  if (isLoading) {
3306
- return /* @__PURE__ */ jsx30("span", { className: "block w-3 h-3 rounded-full border-2 border-muted-foreground/40 border-t-foreground animate-spin" });
3514
+ return /* @__PURE__ */ jsx32("span", { className: "block w-3 h-3 rounded-full border-2 border-muted-foreground/40 border-t-foreground animate-spin" });
3307
3515
  }
3308
- return /* @__PURE__ */ jsx30(
3516
+ return /* @__PURE__ */ jsx32(
3309
3517
  ChevronRight3,
3310
3518
  {
3311
3519
  className: cn28(
@@ -3354,7 +3562,7 @@ function NodeRow({
3354
3562
  },
3355
3563
  [node.id, onSelectionChange]
3356
3564
  );
3357
- return /* @__PURE__ */ jsxs10(
3565
+ return /* @__PURE__ */ jsxs12(
3358
3566
  "li",
3359
3567
  {
3360
3568
  id: `${treeId}-node-${node.id}`,
@@ -3373,13 +3581,13 @@ function NodeRow({
3373
3581
  style: { paddingLeft: depth * indentPx + 8 },
3374
3582
  onClick: handleClick,
3375
3583
  children: [
3376
- /* @__PURE__ */ jsx30(
3584
+ /* @__PURE__ */ jsx32(
3377
3585
  "span",
3378
3586
  {
3379
3587
  className: "shrink-0 flex items-center justify-center w-4 h-4",
3380
3588
  onClick: handleToggle,
3381
3589
  "aria-hidden": true,
3382
- children: /* @__PURE__ */ jsx30(
3590
+ children: /* @__PURE__ */ jsx32(
3383
3591
  ToggleIcon,
3384
3592
  {
3385
3593
  hasChildren: node.hasChildren,
@@ -3389,7 +3597,7 @@ function NodeRow({
3389
3597
  )
3390
3598
  }
3391
3599
  ),
3392
- onSelectionChange && isSelectable && /* @__PURE__ */ jsx30(
3600
+ onSelectionChange && isSelectable && /* @__PURE__ */ jsx32(
3393
3601
  "input",
3394
3602
  {
3395
3603
  type: "checkbox",
@@ -3401,8 +3609,8 @@ function NodeRow({
3401
3609
  tabIndex: -1
3402
3610
  }
3403
3611
  ),
3404
- /* @__PURE__ */ jsx30("span", { className: "flex-1 min-w-0", children: renderNode(node, depth) }),
3405
- node.isError && /* @__PURE__ */ jsx30("span", { className: "shrink-0 text-xs text-destructive", "aria-live": "polite", children: "Failed to load" })
3612
+ /* @__PURE__ */ jsx32("span", { className: "flex-1 min-w-0", children: renderNode(node, depth) }),
3613
+ node.isError && /* @__PURE__ */ jsx32("span", { className: "shrink-0 text-xs text-destructive", "aria-live": "polite", children: "Failed to load" })
3406
3614
  ]
3407
3615
  }
3408
3616
  );
@@ -3422,9 +3630,9 @@ function TreeViewInner({
3422
3630
  className
3423
3631
  }, ref) {
3424
3632
  const treeId = useId2();
3425
- const [focusedId, setFocusedId] = useState4(null);
3633
+ const [focusedId, setFocusedId] = useState5(null);
3426
3634
  const listRef = useRef5(null);
3427
- const [constrainedParent, setConstrainedParent] = useState4(UNCONSTRAINED);
3635
+ const [constrainedParent, setConstrainedParent] = useState5(UNCONSTRAINED);
3428
3636
  const selectionSize = selectedIds?.size ?? 0;
3429
3637
  useEffect5(() => {
3430
3638
  if (selectionSize === 0) setConstrainedParent(UNCONSTRAINED);
@@ -3578,7 +3786,7 @@ function TreeViewInner({
3578
3786
  ]
3579
3787
  );
3580
3788
  if (nodes.length === 0) {
3581
- return /* @__PURE__ */ jsx30(
3789
+ return /* @__PURE__ */ jsx32(
3582
3790
  "div",
3583
3791
  {
3584
3792
  className: cn28(
@@ -3589,7 +3797,7 @@ function TreeViewInner({
3589
3797
  }
3590
3798
  );
3591
3799
  }
3592
- return /* @__PURE__ */ jsx30(
3800
+ return /* @__PURE__ */ jsx32(
3593
3801
  "ul",
3594
3802
  {
3595
3803
  ref: listRef,
@@ -3597,7 +3805,7 @@ function TreeViewInner({
3597
3805
  "aria-label": "Tree",
3598
3806
  className: cn28("outline-none", className),
3599
3807
  onKeyDown: handleKeyDown,
3600
- children: flatNodes.map((flat) => /* @__PURE__ */ jsx30(
3808
+ children: flatNodes.map((flat) => /* @__PURE__ */ jsx32(
3601
3809
  NodeRow,
3602
3810
  {
3603
3811
  flat,
@@ -3622,23 +3830,23 @@ function TreeViewInner({
3622
3830
  var TreeView = forwardRef19(TreeViewInner);
3623
3831
 
3624
3832
  // src/EntityTree/EntityTree.tsx
3625
- import { jsx as jsx31, jsxs as jsxs11 } from "react/jsx-runtime";
3833
+ import { jsx as jsx33, jsxs as jsxs13 } from "react/jsx-runtime";
3626
3834
  function buildCellRow(resolved, activeNodeIdRef, onNodeEdit, localRenderers) {
3627
3835
  return function renderCells(node) {
3628
3836
  const isActive = node.id === activeNodeIdRef.current;
3629
- return /* @__PURE__ */ jsxs11("span", { className: "flex items-center gap-4 min-w-0 w-full group/row", children: [
3837
+ return /* @__PURE__ */ jsxs13("span", { className: "flex items-center gap-4 min-w-0 w-full group/row", children: [
3630
3838
  resolved.map((col) => {
3631
3839
  const Renderer = resolveCellRenderer2(
3632
3840
  col.cellRenderer,
3633
3841
  localRenderers
3634
3842
  );
3635
3843
  const value = node.data[col.key];
3636
- return /* @__PURE__ */ jsx31(
3844
+ return /* @__PURE__ */ jsx33(
3637
3845
  "span",
3638
3846
  {
3639
3847
  className: "shrink-0",
3640
3848
  style: col.width !== void 0 ? { width: col.width } : void 0,
3641
- children: /* @__PURE__ */ jsx31(
3849
+ children: /* @__PURE__ */ jsx33(
3642
3850
  Renderer,
3643
3851
  {
3644
3852
  value,
@@ -3650,7 +3858,7 @@ function buildCellRow(resolved, activeNodeIdRef, onNodeEdit, localRenderers) {
3650
3858
  col.key
3651
3859
  );
3652
3860
  }),
3653
- onNodeEdit && /* @__PURE__ */ jsx31("span", { className: "ml-auto shrink-0", children: /* @__PURE__ */ jsx31(
3861
+ onNodeEdit && /* @__PURE__ */ jsx33("span", { className: "ml-auto shrink-0", children: /* @__PURE__ */ jsx33(
3654
3862
  "button",
3655
3863
  {
3656
3864
  type: "button",
@@ -3663,7 +3871,7 @@ function buildCellRow(resolved, activeNodeIdRef, onNodeEdit, localRenderers) {
3663
3871
  "p-1 rounded hover:bg-background text-muted-foreground hover:text-foreground transition-colors",
3664
3872
  isActive ? "opacity-100" : "opacity-0 group-hover/row:opacity-100"
3665
3873
  ),
3666
- children: /* @__PURE__ */ jsx31(Pencil, { className: "h-3.5 w-3.5" })
3874
+ children: /* @__PURE__ */ jsx33(Pencil, { className: "h-3.5 w-3.5" })
3667
3875
  }
3668
3876
  ) })
3669
3877
  ] });
@@ -3686,7 +3894,7 @@ function renderTreeStatus({
3686
3894
  className
3687
3895
  }) {
3688
3896
  if (isLoading && nodes.length === 0) {
3689
- return /* @__PURE__ */ jsx31(
3897
+ return /* @__PURE__ */ jsx33(
3690
3898
  "div",
3691
3899
  {
3692
3900
  className: cn29(
@@ -3698,7 +3906,7 @@ function renderTreeStatus({
3698
3906
  );
3699
3907
  }
3700
3908
  if (isError) {
3701
- return /* @__PURE__ */ jsx31(
3909
+ return /* @__PURE__ */ jsx33(
3702
3910
  "div",
3703
3911
  {
3704
3912
  className: cn29("py-8 text-center text-sm text-destructive", className),
@@ -3707,7 +3915,7 @@ function renderTreeStatus({
3707
3915
  );
3708
3916
  }
3709
3917
  if (!isLoading && nodes.length === 0) {
3710
- return /* @__PURE__ */ jsxs11(
3918
+ return /* @__PURE__ */ jsxs13(
3711
3919
  "div",
3712
3920
  {
3713
3921
  className: cn29(
@@ -3802,7 +4010,7 @@ function EntityTreeInner(props, ref) {
3802
4010
  className
3803
4011
  });
3804
4012
  if (statusView) return statusView;
3805
- return /* @__PURE__ */ jsx31("div", { className: cn29("rounded-lg border", className), children: /* @__PURE__ */ jsx31(
4013
+ return /* @__PURE__ */ jsx33("div", { className: cn29("rounded-lg border", className), children: /* @__PURE__ */ jsx33(
3806
4014
  TreeView,
3807
4015
  {
3808
4016
  ref: treeRef,
@@ -3824,14 +4032,14 @@ function EntityTreeInner(props, ref) {
3824
4032
  var EntityTree = forwardRef20(EntityTreeInner);
3825
4033
 
3826
4034
  // src/SearchInput/SearchInput.tsx
3827
- import React30, { useMemo as useMemo6, useRef as useRef9, useState as useState7, useEffect as useEffect9 } from "react";
4035
+ import React31, { useMemo as useMemo6, useRef as useRef9, useState as useState8, useEffect as useEffect9 } from "react";
3828
4036
  import { Search as Search2, X as X3, ChevronDown } from "lucide-react";
3829
4037
  import { cn as cn31 } from "@petrarca/sonnet-core";
3830
4038
  import { getFieldTitle as getFieldTitle2 } from "@petrarca/sonnet-core/schema";
3831
4039
  import { isEmptyFilterExpr } from "@petrarca/sonnet-core/search";
3832
4040
 
3833
4041
  // src/SearchInput/useSearchInput.ts
3834
- import { useCallback as useCallback5, useEffect as useEffect6, useMemo as useMemo5, useRef as useRef7, useState as useState5 } from "react";
4042
+ import { useCallback as useCallback5, useEffect as useEffect6, useMemo as useMemo5, useRef as useRef7, useState as useState6 } from "react";
3835
4043
  import { collectTerms } from "@petrarca/sonnet-core/search";
3836
4044
 
3837
4045
  // src/SearchInput/schemaAdapter.ts
@@ -3915,11 +4123,11 @@ function useSearchInput({
3915
4123
  const terms = collectTerms(value);
3916
4124
  return terms.length === 1 && terms[0].key === "search" ? terms[0].value : "";
3917
4125
  })() : "";
3918
- const [inputValue, setInputValue] = useState5(initialInput);
3919
- const [pendingFacet, setPendingFacet] = useState5(
4126
+ const [inputValue, setInputValue] = useState6(initialInput);
4127
+ const [pendingFacet, setPendingFacet] = useState6(
3920
4128
  null
3921
4129
  );
3922
- const [draftTerms, setDraftTerms] = useState5(
4130
+ const [draftTerms, setDraftTerms] = useState6(
3923
4131
  () => isFaceted ? collectTerms(value) : []
3924
4132
  );
3925
4133
  const valueTerms = useMemo5(
@@ -4134,7 +4342,7 @@ function useSearchInput({
4134
4342
 
4135
4343
  // src/SearchInput/widgets/TextSearchWidget.tsx
4136
4344
  import { useRef as useRef8, useEffect as useEffect7 } from "react";
4137
- import { jsx as jsx32 } from "react/jsx-runtime";
4345
+ import { jsx as jsx34 } from "react/jsx-runtime";
4138
4346
  function TextSearchWidget({
4139
4347
  value,
4140
4348
  onChange,
@@ -4147,7 +4355,7 @@ function TextSearchWidget({
4147
4355
  useEffect7(() => {
4148
4356
  if (autoFocus) inputRef.current?.focus();
4149
4357
  }, [autoFocus]);
4150
- return /* @__PURE__ */ jsx32(
4358
+ return /* @__PURE__ */ jsx34(
4151
4359
  Input,
4152
4360
  {
4153
4361
  ref: inputRef,
@@ -4173,9 +4381,9 @@ function TextSearchWidget({
4173
4381
  }
4174
4382
 
4175
4383
  // src/SearchInput/widgets/EnumSearchWidget.tsx
4176
- import { useEffect as useEffect8, useState as useState6 } from "react";
4384
+ import { useEffect as useEffect8, useState as useState7 } from "react";
4177
4385
  import { cn as cn30 } from "@petrarca/sonnet-core";
4178
- import { jsx as jsx33, jsxs as jsxs12 } from "react/jsx-runtime";
4386
+ import { jsx as jsx35, jsxs as jsxs14 } from "react/jsx-runtime";
4179
4387
  function EnumSearchWidget({
4180
4388
  property,
4181
4389
  options: widgetOptions,
@@ -4184,9 +4392,9 @@ function EnumSearchWidget({
4184
4392
  placeholder,
4185
4393
  autoFocus
4186
4394
  }) {
4187
- const [open, setOpen] = useState6(false);
4188
- const [search, setSearch] = useState6("");
4189
- const [highlightedIndex, setHighlightedIndex] = useState6(0);
4395
+ const [open, setOpen] = useState7(false);
4396
+ const [search, setSearch] = useState7("");
4397
+ const [highlightedIndex, setHighlightedIndex] = useState7(0);
4190
4398
  const enumValues = property.enum ?? [];
4191
4399
  const enumNames = widgetOptions.enumNames ?? {};
4192
4400
  const items = enumValues.map((val) => ({
@@ -4239,8 +4447,8 @@ function EnumSearchWidget({
4239
4447
  return;
4240
4448
  }
4241
4449
  }
4242
- return /* @__PURE__ */ jsxs12(Popover, { open, onOpenChange: handleOpenChange, children: [
4243
- /* @__PURE__ */ jsx33(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx33(
4450
+ return /* @__PURE__ */ jsxs14(Popover, { open, onOpenChange: handleOpenChange, children: [
4451
+ /* @__PURE__ */ jsx35(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx35(
4244
4452
  "button",
4245
4453
  {
4246
4454
  type: "button",
@@ -4249,14 +4457,14 @@ function EnumSearchWidget({
4249
4457
  children: placeholder ?? "Select..."
4250
4458
  }
4251
4459
  ) }),
4252
- /* @__PURE__ */ jsxs12(
4460
+ /* @__PURE__ */ jsxs14(
4253
4461
  PopoverContent,
4254
4462
  {
4255
4463
  className: "w-48 p-1",
4256
4464
  align: "start",
4257
4465
  onOpenAutoFocus: (e) => e.preventDefault(),
4258
4466
  children: [
4259
- /* @__PURE__ */ jsx33(
4467
+ /* @__PURE__ */ jsx35(
4260
4468
  "input",
4261
4469
  {
4262
4470
  autoFocus: true,
@@ -4267,9 +4475,9 @@ function EnumSearchWidget({
4267
4475
  className: "w-full px-2 py-1.5 text-sm bg-transparent outline-none border-b border-border mb-1 placeholder:text-muted-foreground"
4268
4476
  }
4269
4477
  ),
4270
- /* @__PURE__ */ jsxs12("div", { children: [
4271
- filtered.length === 0 && /* @__PURE__ */ jsx33("p", { className: "px-2 py-1.5 text-sm text-muted-foreground", children: "No matches" }),
4272
- filtered.map((item, i) => /* @__PURE__ */ jsx33(
4478
+ /* @__PURE__ */ jsxs14("div", { children: [
4479
+ filtered.length === 0 && /* @__PURE__ */ jsx35("p", { className: "px-2 py-1.5 text-sm text-muted-foreground", children: "No matches" }),
4480
+ filtered.map((item, i) => /* @__PURE__ */ jsx35(
4273
4481
  "button",
4274
4482
  {
4275
4483
  type: "button",
@@ -4312,7 +4520,7 @@ var DEFAULT_SEARCH_WIDGETS = {
4312
4520
  };
4313
4521
 
4314
4522
  // src/SearchInput/SearchInput.tsx
4315
- import { Fragment as Fragment3, jsx as jsx34, jsxs as jsxs13 } from "react/jsx-runtime";
4523
+ import { Fragment as Fragment3, jsx as jsx36, jsxs as jsxs15 } from "react/jsx-runtime";
4316
4524
  function resolveSearchDefaults(props) {
4317
4525
  return {
4318
4526
  mode: props.mode ?? "explicit",
@@ -4332,8 +4540,8 @@ function FacetPicker({
4332
4540
  acceptFacet,
4333
4541
  inputRef
4334
4542
  }) {
4335
- return /* @__PURE__ */ jsxs13(Popover, { open: pickerVisible, onOpenChange: setPickerOpen, modal: false, children: [
4336
- /* @__PURE__ */ jsx34(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx34(
4543
+ return /* @__PURE__ */ jsxs15(Popover, { open: pickerVisible, onOpenChange: setPickerOpen, modal: false, children: [
4544
+ /* @__PURE__ */ jsx36(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx36(
4337
4545
  "button",
4338
4546
  {
4339
4547
  type: "button",
@@ -4344,17 +4552,17 @@ function FacetPicker({
4344
4552
  setPickerOpen((o) => !o);
4345
4553
  inputRef.current?.focus();
4346
4554
  },
4347
- children: /* @__PURE__ */ jsx34(ChevronDown, { className: "h-3 w-3" })
4555
+ children: /* @__PURE__ */ jsx36(ChevronDown, { className: "h-3 w-3" })
4348
4556
  }
4349
4557
  ) }),
4350
- /* @__PURE__ */ jsx34(
4558
+ /* @__PURE__ */ jsx36(
4351
4559
  PopoverContent,
4352
4560
  {
4353
4561
  className: cn31("w-44 p-1", !hasFacetsToShow && "hidden"),
4354
4562
  align: "start",
4355
4563
  onOpenAutoFocus: (e) => e.preventDefault(),
4356
4564
  onFocusOutside: (e) => e.preventDefault(),
4357
- children: filteredFacets.map((facet, i) => /* @__PURE__ */ jsx34(
4565
+ children: filteredFacets.map((facet, i) => /* @__PURE__ */ jsx36(
4358
4566
  "button",
4359
4567
  {
4360
4568
  type: "button",
@@ -4392,7 +4600,7 @@ function ValueEntry({
4392
4600
  onInputFocus
4393
4601
  }) {
4394
4602
  if (pendingFacet && PendingWidget) {
4395
- return /* @__PURE__ */ jsx34(
4603
+ return /* @__PURE__ */ jsx36(
4396
4604
  PendingWidget,
4397
4605
  {
4398
4606
  property: pendingFacet.property,
@@ -4414,7 +4622,7 @@ function ValueEntry({
4414
4622
  }
4415
4623
  );
4416
4624
  }
4417
- return /* @__PURE__ */ jsx34(
4625
+ return /* @__PURE__ */ jsx36(
4418
4626
  Input,
4419
4627
  {
4420
4628
  ref: inputRef,
@@ -4483,10 +4691,10 @@ function ActiveChips({
4483
4691
  schema,
4484
4692
  onRemove
4485
4693
  }) {
4486
- return /* @__PURE__ */ jsx34(Fragment3, { children: terms.map((term, i) => {
4694
+ return /* @__PURE__ */ jsx36(Fragment3, { children: terms.map((term, i) => {
4487
4695
  const property = schema?.properties?.[term.key];
4488
4696
  const label = property ? getFieldTitle2(term.key, property) : term.key;
4489
- return /* @__PURE__ */ jsx34(
4697
+ return /* @__PURE__ */ jsx36(
4490
4698
  FilterChip,
4491
4699
  {
4492
4700
  label: `${label}: ${term.value}`,
@@ -4510,8 +4718,8 @@ function SearchActions({
4510
4718
  onClear,
4511
4719
  onCommit
4512
4720
  }) {
4513
- return /* @__PURE__ */ jsxs13(Fragment3, { children: [
4514
- !isEmpty && /* @__PURE__ */ jsx34(
4721
+ return /* @__PURE__ */ jsxs15(Fragment3, { children: [
4722
+ !isEmpty && /* @__PURE__ */ jsx36(
4515
4723
  "button",
4516
4724
  {
4517
4725
  type: "button",
@@ -4521,10 +4729,10 @@ function SearchActions({
4521
4729
  },
4522
4730
  className: "text-muted-foreground hover:text-foreground transition-colors shrink-0",
4523
4731
  "aria-label": "Clear search",
4524
- children: /* @__PURE__ */ jsx34(X3, { className: "h-4 w-4" })
4732
+ children: /* @__PURE__ */ jsx36(X3, { className: "h-4 w-4" })
4525
4733
  }
4526
4734
  ),
4527
- showSearchButton && mode === "explicit" && /* @__PURE__ */ jsx34(
4735
+ showSearchButton && mode === "explicit" && /* @__PURE__ */ jsx36(
4528
4736
  Button,
4529
4737
  {
4530
4738
  type: "button",
@@ -4556,9 +4764,9 @@ function SearchInput(props) {
4556
4764
  const { mode, debounceMs, minChars, showSearchButton, disabled } = resolveSearchDefaults(props);
4557
4765
  const inputRef = useRef9(null);
4558
4766
  const containerRef = useRef9(null);
4559
- const [pickerOpen, setPickerOpen] = useState7(false);
4560
- const [highlightedIndex, setHighlightedIndex] = useState7(-1);
4561
- const [pickerNavigated, setPickerNavigated] = useState7(false);
4767
+ const [pickerOpen, setPickerOpen] = useState8(false);
4768
+ const [highlightedIndex, setHighlightedIndex] = useState8(-1);
4769
+ const [pickerNavigated, setPickerNavigated] = useState8(false);
4562
4770
  useEffect9(() => {
4563
4771
  if (!pickerOpen) return;
4564
4772
  function handleMouseDown(e) {
@@ -4609,7 +4817,7 @@ function SearchInput(props) {
4609
4817
  const showFacetControls = isFaceted && !pendingFacet;
4610
4818
  const pickerVisible = showFacetControls && pickerOpen;
4611
4819
  const hasFacetsToShow = pickerVisible && filteredFacets.length > 0;
4612
- const acceptFacet = React30.useCallback(
4820
+ const acceptFacet = React31.useCallback(
4613
4821
  (facet) => {
4614
4822
  selectFacet(facet);
4615
4823
  setPickerOpen(false);
@@ -4633,7 +4841,7 @@ function SearchInput(props) {
4633
4841
  acceptFacet,
4634
4842
  handleKeyDown
4635
4843
  };
4636
- return /* @__PURE__ */ jsxs13(
4844
+ return /* @__PURE__ */ jsxs15(
4637
4845
  "div",
4638
4846
  {
4639
4847
  ref: containerRef,
@@ -4650,8 +4858,8 @@ function SearchInput(props) {
4650
4858
  }
4651
4859
  },
4652
4860
  children: [
4653
- /* @__PURE__ */ jsx34(Search2, { className: "h-4 w-4 text-muted-foreground shrink-0" }),
4654
- isFaceted && /* @__PURE__ */ jsx34(
4861
+ /* @__PURE__ */ jsx36(Search2, { className: "h-4 w-4 text-muted-foreground shrink-0" }),
4862
+ isFaceted && /* @__PURE__ */ jsx36(
4655
4863
  ActiveChips,
4656
4864
  {
4657
4865
  terms: activeTerms,
@@ -4659,12 +4867,12 @@ function SearchInput(props) {
4659
4867
  onRemove: handleRemoveTerm
4660
4868
  }
4661
4869
  ),
4662
- pendingFacet && /* @__PURE__ */ jsxs13("span", { className: "inline-flex items-center gap-1 rounded-full bg-muted px-2 py-0.5 text-xs font-medium text-muted-foreground", children: [
4870
+ pendingFacet && /* @__PURE__ */ jsxs15("span", { className: "inline-flex items-center gap-1 rounded-full bg-muted px-2 py-0.5 text-xs font-medium text-muted-foreground", children: [
4663
4871
  pendingFacet.label,
4664
4872
  ":"
4665
4873
  ] }),
4666
- /* @__PURE__ */ jsxs13("div", { className: "flex items-center gap-1 flex-1 min-w-[120px]", children: [
4667
- showFacetControls && /* @__PURE__ */ jsx34(
4874
+ /* @__PURE__ */ jsxs15("div", { className: "flex items-center gap-1 flex-1 min-w-[120px]", children: [
4875
+ showFacetControls && /* @__PURE__ */ jsx36(
4668
4876
  FacetPicker,
4669
4877
  {
4670
4878
  pickerVisible,
@@ -4677,7 +4885,7 @@ function SearchInput(props) {
4677
4885
  inputRef
4678
4886
  }
4679
4887
  ),
4680
- /* @__PURE__ */ jsx34(
4888
+ /* @__PURE__ */ jsx36(
4681
4889
  ValueEntry,
4682
4890
  {
4683
4891
  pendingFacet,
@@ -4701,7 +4909,7 @@ function SearchInput(props) {
4701
4909
  }
4702
4910
  )
4703
4911
  ] }),
4704
- /* @__PURE__ */ jsx34(
4912
+ /* @__PURE__ */ jsx36(
4705
4913
  SearchActions,
4706
4914
  {
4707
4915
  isEmpty,
@@ -4716,14 +4924,14 @@ function SearchInput(props) {
4716
4924
  );
4717
4925
  }
4718
4926
  function FilterChip({ label, onRemove }) {
4719
- return /* @__PURE__ */ jsxs13(
4927
+ return /* @__PURE__ */ jsxs15(
4720
4928
  Badge,
4721
4929
  {
4722
4930
  variant: "secondary",
4723
4931
  className: "inline-flex items-center gap-1 px-2 py-0.5 text-xs font-medium rounded-full",
4724
4932
  children: [
4725
4933
  label,
4726
- /* @__PURE__ */ jsx34(
4934
+ /* @__PURE__ */ jsx36(
4727
4935
  "button",
4728
4936
  {
4729
4937
  type: "button",
@@ -4733,7 +4941,7 @@ function FilterChip({ label, onRemove }) {
4733
4941
  },
4734
4942
  className: "ml-0.5 hover:text-destructive transition-colors",
4735
4943
  "aria-label": `Remove filter ${label}`,
4736
- children: /* @__PURE__ */ jsx34(X3, { className: "h-3 w-3" })
4944
+ children: /* @__PURE__ */ jsx36(X3, { className: "h-3 w-3" })
4737
4945
  }
4738
4946
  )
4739
4947
  ]
@@ -4743,9 +4951,9 @@ function FilterChip({ label, onRemove }) {
4743
4951
 
4744
4952
  // src/Clipboard/ClipboardButton.tsx
4745
4953
  import { Copy } from "lucide-react";
4746
- import { jsx as jsx35 } from "react/jsx-runtime";
4954
+ import { jsx as jsx37 } from "react/jsx-runtime";
4747
4955
  function ClipboardButton({ hasItems, onClick }) {
4748
- return /* @__PURE__ */ jsx35(
4956
+ return /* @__PURE__ */ jsx37(
4749
4957
  Button,
4750
4958
  {
4751
4959
  variant: "ghost",
@@ -4756,7 +4964,7 @@ function ClipboardButton({ hasItems, onClick }) {
4756
4964
  opacity: hasItems ? 1 : 0.4,
4757
4965
  cursor: hasItems ? "pointer" : "not-allowed"
4758
4966
  },
4759
- children: /* @__PURE__ */ jsx35(Copy, { size: 16 })
4967
+ children: /* @__PURE__ */ jsx37(Copy, { size: 16 })
4760
4968
  }
4761
4969
  );
4762
4970
  }
@@ -4764,13 +4972,13 @@ var ClipboardButton_default = ClipboardButton;
4764
4972
 
4765
4973
  // src/Clipboard/ClipboardItem.tsx
4766
4974
  import { X as X4, Plus } from "lucide-react";
4767
- import { jsx as jsx36, jsxs as jsxs14 } from "react/jsx-runtime";
4975
+ import { jsx as jsx38, jsxs as jsxs16 } from "react/jsx-runtime";
4768
4976
  function ClipboardItemComponent({ item, onAddItem, onRemove }) {
4769
4977
  const handleAddClick = (e) => {
4770
4978
  const keepInClipboard = e.shiftKey;
4771
4979
  onAddItem(item, keepInClipboard);
4772
4980
  };
4773
- return /* @__PURE__ */ jsx36(
4981
+ return /* @__PURE__ */ jsx38(
4774
4982
  "div",
4775
4983
  {
4776
4984
  className: "p-3 rounded mb-2",
@@ -4778,17 +4986,17 @@ function ClipboardItemComponent({ item, onAddItem, onRemove }) {
4778
4986
  borderLeft: `4px solid ${item.color}`,
4779
4987
  backgroundColor: "#f8f9fa"
4780
4988
  },
4781
- children: /* @__PURE__ */ jsxs14(SimpleGroup, { justify: "space-between", wrap: "nowrap", align: "flex-start", children: [
4782
- /* @__PURE__ */ jsxs14("div", { className: "flex-1 min-w-0 overflow-hidden", children: [
4783
- /* @__PURE__ */ jsx36("p", { className: "text-sm font-semibold truncate", children: item.label }),
4784
- /* @__PURE__ */ jsx36("p", { className: "text-xs text-muted-foreground truncate", children: item.displayName }),
4785
- /* @__PURE__ */ jsxs14("p", { className: "text-xs text-muted-foreground font-mono", children: [
4989
+ children: /* @__PURE__ */ jsxs16(SimpleGroup, { justify: "space-between", wrap: "nowrap", align: "flex-start", children: [
4990
+ /* @__PURE__ */ jsxs16("div", { className: "flex-1 min-w-0 overflow-hidden", children: [
4991
+ /* @__PURE__ */ jsx38("p", { className: "text-sm font-semibold truncate", children: item.label }),
4992
+ /* @__PURE__ */ jsx38("p", { className: "text-xs text-muted-foreground truncate", children: item.displayName }),
4993
+ /* @__PURE__ */ jsxs16("p", { className: "text-xs text-muted-foreground font-mono", children: [
4786
4994
  "#",
4787
4995
  item.entityId
4788
4996
  ] })
4789
4997
  ] }),
4790
- /* @__PURE__ */ jsxs14(SimpleGroup, { gap: 4, wrap: "nowrap", style: { flexShrink: 0 }, children: [
4791
- /* @__PURE__ */ jsxs14(
4998
+ /* @__PURE__ */ jsxs16(SimpleGroup, { gap: 4, wrap: "nowrap", style: { flexShrink: 0 }, children: [
4999
+ /* @__PURE__ */ jsxs16(
4792
5000
  Button,
4793
5001
  {
4794
5002
  size: "sm",
@@ -4796,19 +5004,19 @@ function ClipboardItemComponent({ item, onAddItem, onRemove }) {
4796
5004
  onClick: handleAddClick,
4797
5005
  title: "Click to add and remove from clipboard, Shift+Click to keep in clipboard",
4798
5006
  children: [
4799
- /* @__PURE__ */ jsx36(Plus, { size: 16 }),
5007
+ /* @__PURE__ */ jsx38(Plus, { size: 16 }),
4800
5008
  "Add"
4801
5009
  ]
4802
5010
  }
4803
5011
  ),
4804
- /* @__PURE__ */ jsx36(
5012
+ /* @__PURE__ */ jsx38(
4805
5013
  Button,
4806
5014
  {
4807
5015
  size: "sm",
4808
5016
  variant: "ghost",
4809
5017
  onClick: () => onRemove(item.id),
4810
5018
  title: "Remove from clipboard",
4811
- children: /* @__PURE__ */ jsx36(X4, { size: 16 })
5019
+ children: /* @__PURE__ */ jsx38(X4, { size: 16 })
4812
5020
  }
4813
5021
  )
4814
5022
  ] })
@@ -4906,16 +5114,16 @@ var useClipboard = create()(
4906
5114
  var clipboardStore_default = useClipboard;
4907
5115
 
4908
5116
  // src/Clipboard/ClipboardMenu.tsx
4909
- import { jsx as jsx37, jsxs as jsxs15 } from "react/jsx-runtime";
5117
+ import { jsx as jsx39, jsxs as jsxs17 } from "react/jsx-runtime";
4910
5118
  function ClipboardMenu({ onAddItem }) {
4911
5119
  const { items, removeItem, clear } = clipboardStore_default();
4912
5120
  if (items.length === 0) {
4913
- return /* @__PURE__ */ jsxs15("div", { style: { padding: "16px", textAlign: "center", width: "300px" }, children: [
4914
- /* @__PURE__ */ jsx37("p", { className: "text-sm text-muted-foreground", children: "No items in clipboard" }),
4915
- /* @__PURE__ */ jsx37("p", { className: "text-xs text-muted-foreground mt-1", children: 'Right-click a node and select "Copy"' })
5121
+ return /* @__PURE__ */ jsxs17("div", { style: { padding: "16px", textAlign: "center", width: "300px" }, children: [
5122
+ /* @__PURE__ */ jsx39("p", { className: "text-sm text-muted-foreground", children: "No items in clipboard" }),
5123
+ /* @__PURE__ */ jsx39("p", { className: "text-xs text-muted-foreground mt-1", children: 'Right-click a node and select "Copy"' })
4916
5124
  ] });
4917
5125
  }
4918
- return /* @__PURE__ */ jsxs15(
5126
+ return /* @__PURE__ */ jsxs17(
4919
5127
  "div",
4920
5128
  {
4921
5129
  style: {
@@ -4926,7 +5134,7 @@ function ClipboardMenu({ onAddItem }) {
4926
5134
  maxHeight: "500px"
4927
5135
  },
4928
5136
  children: [
4929
- /* @__PURE__ */ jsx37(ScrollArea, { className: "flex-1 p-3 min-h-0", children: /* @__PURE__ */ jsx37(SimpleStack, { gap: 0, children: items.map((item) => /* @__PURE__ */ jsx37(
5137
+ /* @__PURE__ */ jsx39(ScrollArea, { className: "flex-1 p-3 min-h-0", children: /* @__PURE__ */ jsx39(SimpleStack, { gap: 0, children: items.map((item) => /* @__PURE__ */ jsx39(
4930
5138
  ClipboardItem_default,
4931
5139
  {
4932
5140
  item,
@@ -4935,8 +5143,8 @@ function ClipboardMenu({ onAddItem }) {
4935
5143
  },
4936
5144
  item.id
4937
5145
  )) }) }),
4938
- /* @__PURE__ */ jsx37(Separator2, {}),
4939
- /* @__PURE__ */ jsx37("div", { style: { padding: "8px 12px", flexShrink: 0 }, children: /* @__PURE__ */ jsxs15(
5146
+ /* @__PURE__ */ jsx39(Separator2, {}),
5147
+ /* @__PURE__ */ jsx39("div", { style: { padding: "8px 12px", flexShrink: 0 }, children: /* @__PURE__ */ jsxs17(
4940
5148
  Button,
4941
5149
  {
4942
5150
  className: "w-full",
@@ -4944,7 +5152,7 @@ function ClipboardMenu({ onAddItem }) {
4944
5152
  size: "sm",
4945
5153
  onClick: clear,
4946
5154
  children: [
4947
- /* @__PURE__ */ jsx37(Trash2, { size: 16 }),
5155
+ /* @__PURE__ */ jsx39(Trash2, { size: 16 }),
4948
5156
  "Clear All (",
4949
5157
  items.length,
4950
5158
  ")"
@@ -5027,6 +5235,8 @@ export {
5027
5235
  Popover,
5028
5236
  PopoverContent,
5029
5237
  PopoverTrigger,
5238
+ PropertyList,
5239
+ PropertyValue,
5030
5240
  ResizeHandle,
5031
5241
  ScrollArea,
5032
5242
  ScrollBar,