kennel-plugins 0.1.2 → 0.1.4
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/{chunk-454D7WI6.js → chunk-FLSLPC4P.js} +13 -471
- package/dist/hooks.d.ts +12 -0
- package/dist/hooks.js +22 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -7
- package/dist/page.d.ts +4 -125
- package/dist/page.js +3 -7
- package/dist/types.d.ts +8 -1
- package/package.json +5 -1
|
@@ -3752,7 +3752,7 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
|
|
|
3752
3752
|
const _normalized = cached(() => normalizeDef(def));
|
|
3753
3753
|
const generateFastpass = (shape) => {
|
|
3754
3754
|
const doc = new Doc(["shape", "payload", "ctx"]);
|
|
3755
|
-
const
|
|
3755
|
+
const normalized = _normalized.value;
|
|
3756
3756
|
const parseStr = (key) => {
|
|
3757
3757
|
const k = esc(key);
|
|
3758
3758
|
return `shape[${k}]._zod.run({ value: input[${k}], issues: [] }, ctx)`;
|
|
@@ -3760,11 +3760,11 @@ var $ZodObjectJIT = /* @__PURE__ */ $constructor("$ZodObjectJIT", (inst, def) =>
|
|
|
3760
3760
|
doc.write(`const input = payload.value;`);
|
|
3761
3761
|
const ids = /* @__PURE__ */ Object.create(null);
|
|
3762
3762
|
let counter = 0;
|
|
3763
|
-
for (const key of
|
|
3763
|
+
for (const key of normalized.keys) {
|
|
3764
3764
|
ids[key] = `key_${counter++}`;
|
|
3765
3765
|
}
|
|
3766
3766
|
doc.write(`const newResult = {};`);
|
|
3767
|
-
for (const key of
|
|
3767
|
+
for (const key of normalized.keys) {
|
|
3768
3768
|
const id = ids[key];
|
|
3769
3769
|
const k = esc(key);
|
|
3770
3770
|
const schema = shape[key];
|
|
@@ -15140,23 +15140,23 @@ function fromJSONSchema(schema, params) {
|
|
|
15140
15140
|
if (typeof schema === "boolean") {
|
|
15141
15141
|
return schema ? z.any() : z.never();
|
|
15142
15142
|
}
|
|
15143
|
-
let
|
|
15143
|
+
let normalized;
|
|
15144
15144
|
try {
|
|
15145
|
-
|
|
15145
|
+
normalized = JSON.parse(JSON.stringify(schema));
|
|
15146
15146
|
} catch {
|
|
15147
15147
|
throw new Error("fromJSONSchema input is not valid JSON (possibly cyclic); use $defs/$ref for recursive schemas");
|
|
15148
15148
|
}
|
|
15149
|
-
const version2 = detectVersion(
|
|
15150
|
-
const defs =
|
|
15149
|
+
const version2 = detectVersion(normalized, params?.defaultTarget);
|
|
15150
|
+
const defs = normalized.$defs || normalized.definitions || {};
|
|
15151
15151
|
const ctx = {
|
|
15152
15152
|
version: version2,
|
|
15153
15153
|
defs,
|
|
15154
15154
|
refs: /* @__PURE__ */ new Map(),
|
|
15155
15155
|
processing: /* @__PURE__ */ new Set(),
|
|
15156
|
-
rootSchema:
|
|
15156
|
+
rootSchema: normalized,
|
|
15157
15157
|
registry: params?.registry ?? globalRegistry
|
|
15158
15158
|
};
|
|
15159
|
-
return convertSchema(
|
|
15159
|
+
return convertSchema(normalized, ctx);
|
|
15160
15160
|
}
|
|
15161
15161
|
|
|
15162
15162
|
// ../../node_modules/.bun/zod@4.4.3/node_modules/zod/v4/classic/coerce.js
|
|
@@ -15270,13 +15270,6 @@ var project = external_exports.object({
|
|
|
15270
15270
|
relativePath: external_exports.string(),
|
|
15271
15271
|
worktree: external_exports.string()
|
|
15272
15272
|
});
|
|
15273
|
-
var skill = external_exports.object({
|
|
15274
|
-
description: external_exports.string().optional(),
|
|
15275
|
-
name: external_exports.string(),
|
|
15276
|
-
openHref: external_exports.string().optional(),
|
|
15277
|
-
relativePath: external_exports.string(),
|
|
15278
|
-
source: external_exports.enum(["global", "local"])
|
|
15279
|
-
});
|
|
15280
15273
|
var session = external_exports.object({
|
|
15281
15274
|
client: external_exports.enum(["claude", "codex", "cursor", "opencode", "pi"]),
|
|
15282
15275
|
href: external_exports.string().optional(),
|
|
@@ -15306,6 +15299,7 @@ var workspace = external_exports.object({
|
|
|
15306
15299
|
var plugin = external_exports.object({
|
|
15307
15300
|
count: external_exports.number().optional(),
|
|
15308
15301
|
error: external_exports.string().optional(),
|
|
15302
|
+
icon: external_exports.object({ paths: external_exports.array(external_exports.string().min(1)).min(1) }).optional(),
|
|
15309
15303
|
id: external_exports.string(),
|
|
15310
15304
|
label: external_exports.string()
|
|
15311
15305
|
});
|
|
@@ -15323,7 +15317,6 @@ var folderMetadataSchema = external_exports.object({
|
|
|
15323
15317
|
plugins: plugins.optional(),
|
|
15324
15318
|
projects: items(project),
|
|
15325
15319
|
sessions: items(session),
|
|
15326
|
-
skills: items(skill).optional(),
|
|
15327
15320
|
workspace: workspace.optional()
|
|
15328
15321
|
});
|
|
15329
15322
|
var collection = coreCollectionSchema;
|
|
@@ -15347,7 +15340,6 @@ var metadataSchemas = {
|
|
|
15347
15340
|
configWarnings: external_exports.array(external_exports.string()).optional(),
|
|
15348
15341
|
plugins: plugins.optional()
|
|
15349
15342
|
}),
|
|
15350
|
-
skills: external_exports.object({ ...folder, skills: items(skill) }),
|
|
15351
15343
|
// Legacy selectors currently return the complete metadata payload.
|
|
15352
15344
|
sessions: folderMetadataSchema,
|
|
15353
15345
|
calendar: folderMetadataSchema,
|
|
@@ -15527,7 +15519,7 @@ function url2(value) {
|
|
|
15527
15519
|
}
|
|
15528
15520
|
function tabSection(tab) {
|
|
15529
15521
|
if (tab === "files") return "notes";
|
|
15530
|
-
if (tab === "projects" || tab === "sessions"
|
|
15522
|
+
if (tab === "projects" || tab === "sessions") return tab;
|
|
15531
15523
|
return void 0;
|
|
15532
15524
|
}
|
|
15533
15525
|
function decodeFolderPathId(id) {
|
|
@@ -15579,7 +15571,7 @@ function parseViewerRoute(value) {
|
|
|
15579
15571
|
}
|
|
15580
15572
|
};
|
|
15581
15573
|
}
|
|
15582
|
-
if (section === "notes" || section === "projects" || section === "sessions"
|
|
15574
|
+
if (section === "notes" || section === "projects" || section === "sessions") {
|
|
15583
15575
|
return { ...route, section };
|
|
15584
15576
|
}
|
|
15585
15577
|
if (section === "document" && parts[3]) {
|
|
@@ -15872,461 +15864,11 @@ function FilePreviewList({ paths }) {
|
|
|
15872
15864
|
return /* @__PURE__ */ jsx5("span", { className: "flex min-w-0 flex-wrap gap-2", children: paths.map((path) => /* @__PURE__ */ jsx5(FilePreview, { path }, path)) });
|
|
15873
15865
|
}
|
|
15874
15866
|
|
|
15875
|
-
// ../ui/src/components/folder-filter-bar.tsx
|
|
15876
|
-
import { createContext, useContext } from "react";
|
|
15877
|
-
import { Check as Check2, Folder, FolderSearch } from "lucide-react";
|
|
15878
|
-
|
|
15879
|
-
// ../ui/src/components/badge.tsx
|
|
15880
|
-
import { cva as cva2 } from "class-variance-authority";
|
|
15881
|
-
import { Slot as SlotPrimitive } from "radix-ui";
|
|
15882
|
-
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
15883
|
-
var badgeVariants = cva2(
|
|
15884
|
-
"inline-flex items-center justify-center rounded-full border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden",
|
|
15885
|
-
{
|
|
15886
|
-
variants: {
|
|
15887
|
-
variant: {
|
|
15888
|
-
default: "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90",
|
|
15889
|
-
secondary: "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90",
|
|
15890
|
-
destructive: "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/60",
|
|
15891
|
-
outline: "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground"
|
|
15892
|
-
}
|
|
15893
|
-
},
|
|
15894
|
-
defaultVariants: {
|
|
15895
|
-
variant: "default"
|
|
15896
|
-
}
|
|
15897
|
-
}
|
|
15898
|
-
);
|
|
15899
|
-
function Badge({
|
|
15900
|
-
className,
|
|
15901
|
-
variant,
|
|
15902
|
-
asChild = false,
|
|
15903
|
-
...props
|
|
15904
|
-
}) {
|
|
15905
|
-
const Comp = asChild ? SlotPrimitive.Slot : "span";
|
|
15906
|
-
return /* @__PURE__ */ jsx6(
|
|
15907
|
-
Comp,
|
|
15908
|
-
{
|
|
15909
|
-
"data-slot": "badge",
|
|
15910
|
-
className: cn(badgeVariants({ variant }), className),
|
|
15911
|
-
...props
|
|
15912
|
-
}
|
|
15913
|
-
);
|
|
15914
|
-
}
|
|
15915
|
-
|
|
15916
|
-
// ../ui/src/components/command.tsx
|
|
15917
|
-
import { Command as CommandPrimitive } from "cmdk";
|
|
15918
|
-
import { SearchIcon } from "lucide-react";
|
|
15919
|
-
import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
15920
|
-
function Command({
|
|
15921
|
-
className,
|
|
15922
|
-
...props
|
|
15923
|
-
}) {
|
|
15924
|
-
return /* @__PURE__ */ jsx7(
|
|
15925
|
-
CommandPrimitive,
|
|
15926
|
-
{
|
|
15927
|
-
"data-slot": "command",
|
|
15928
|
-
className: cn(
|
|
15929
|
-
`bg-popover text-popover-foreground flex h-full w-full flex-col
|
|
15930
|
-
overflow-hidden rounded-md`,
|
|
15931
|
-
className
|
|
15932
|
-
),
|
|
15933
|
-
...props
|
|
15934
|
-
}
|
|
15935
|
-
);
|
|
15936
|
-
}
|
|
15937
|
-
function CommandInput({
|
|
15938
|
-
className,
|
|
15939
|
-
...props
|
|
15940
|
-
}) {
|
|
15941
|
-
return /* @__PURE__ */ jsxs3(
|
|
15942
|
-
"div",
|
|
15943
|
-
{
|
|
15944
|
-
"data-slot": "command-input-wrapper",
|
|
15945
|
-
className: "flex h-9 items-center gap-2 border-b px-3",
|
|
15946
|
-
children: [
|
|
15947
|
-
/* @__PURE__ */ jsx7(SearchIcon, { className: "size-4 shrink-0 opacity-50" }),
|
|
15948
|
-
/* @__PURE__ */ jsx7(
|
|
15949
|
-
CommandPrimitive.Input,
|
|
15950
|
-
{
|
|
15951
|
-
"data-slot": "command-input",
|
|
15952
|
-
className: cn(
|
|
15953
|
-
`placeholder:text-muted-foreground flex h-10 w-full rounded-md
|
|
15954
|
-
bg-transparent py-3 text-sm outline-hidden disabled:cursor-not-allowed
|
|
15955
|
-
disabled:opacity-50`,
|
|
15956
|
-
className
|
|
15957
|
-
),
|
|
15958
|
-
...props
|
|
15959
|
-
}
|
|
15960
|
-
)
|
|
15961
|
-
]
|
|
15962
|
-
}
|
|
15963
|
-
);
|
|
15964
|
-
}
|
|
15965
|
-
function CommandList({
|
|
15966
|
-
className,
|
|
15967
|
-
...props
|
|
15968
|
-
}) {
|
|
15969
|
-
return /* @__PURE__ */ jsx7(
|
|
15970
|
-
CommandPrimitive.List,
|
|
15971
|
-
{
|
|
15972
|
-
"data-slot": "command-list",
|
|
15973
|
-
className: cn(
|
|
15974
|
-
"max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto",
|
|
15975
|
-
className
|
|
15976
|
-
),
|
|
15977
|
-
...props
|
|
15978
|
-
}
|
|
15979
|
-
);
|
|
15980
|
-
}
|
|
15981
|
-
function CommandEmpty({
|
|
15982
|
-
...props
|
|
15983
|
-
}) {
|
|
15984
|
-
return /* @__PURE__ */ jsx7(
|
|
15985
|
-
CommandPrimitive.Empty,
|
|
15986
|
-
{
|
|
15987
|
-
"data-slot": "command-empty",
|
|
15988
|
-
className: "py-6 text-center text-sm",
|
|
15989
|
-
...props
|
|
15990
|
-
}
|
|
15991
|
-
);
|
|
15992
|
-
}
|
|
15993
|
-
function CommandGroup({
|
|
15994
|
-
className,
|
|
15995
|
-
...props
|
|
15996
|
-
}) {
|
|
15997
|
-
return /* @__PURE__ */ jsx7(
|
|
15998
|
-
CommandPrimitive.Group,
|
|
15999
|
-
{
|
|
16000
|
-
"data-slot": "command-group",
|
|
16001
|
-
className: cn(
|
|
16002
|
-
`text-foreground [&_[cmdk-group-heading]]:text-muted-foreground
|
|
16003
|
-
overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2
|
|
16004
|
-
[&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs
|
|
16005
|
-
[&_[cmdk-group-heading]]:font-medium`,
|
|
16006
|
-
className
|
|
16007
|
-
),
|
|
16008
|
-
...props
|
|
16009
|
-
}
|
|
16010
|
-
);
|
|
16011
|
-
}
|
|
16012
|
-
function CommandItem({
|
|
16013
|
-
className,
|
|
16014
|
-
...props
|
|
16015
|
-
}) {
|
|
16016
|
-
return /* @__PURE__ */ jsx7(
|
|
16017
|
-
CommandPrimitive.Item,
|
|
16018
|
-
{
|
|
16019
|
-
"data-slot": "command-item",
|
|
16020
|
-
className: cn(
|
|
16021
|
-
`data-[selected=true]:bg-accent
|
|
16022
|
-
data-[selected=true]:text-accent-foreground
|
|
16023
|
-
[&_svg:not([class*='text-'])]:text-muted-foreground relative flex
|
|
16024
|
-
cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm
|
|
16025
|
-
outline-hidden select-none data-[disabled=true]:pointer-events-none
|
|
16026
|
-
data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none
|
|
16027
|
-
[&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4`,
|
|
16028
|
-
className
|
|
16029
|
-
),
|
|
16030
|
-
...props
|
|
16031
|
-
}
|
|
16032
|
-
);
|
|
16033
|
-
}
|
|
16034
|
-
|
|
16035
|
-
// ../ui/src/components/popover.tsx
|
|
16036
|
-
import { Popover as PopoverPrimitive } from "radix-ui";
|
|
16037
|
-
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
16038
|
-
function Popover({
|
|
16039
|
-
...props
|
|
16040
|
-
}) {
|
|
16041
|
-
return /* @__PURE__ */ jsx8(PopoverPrimitive.Root, { "data-slot": "popover", ...props });
|
|
16042
|
-
}
|
|
16043
|
-
function PopoverTrigger({
|
|
16044
|
-
...props
|
|
16045
|
-
}) {
|
|
16046
|
-
return /* @__PURE__ */ jsx8(PopoverPrimitive.Trigger, { "data-slot": "popover-trigger", ...props });
|
|
16047
|
-
}
|
|
16048
|
-
function PopoverContent({
|
|
16049
|
-
className,
|
|
16050
|
-
align = "center",
|
|
16051
|
-
sideOffset = 4,
|
|
16052
|
-
...props
|
|
16053
|
-
}) {
|
|
16054
|
-
return /* @__PURE__ */ jsx8(PopoverPrimitive.Portal, { children: /* @__PURE__ */ jsx8(
|
|
16055
|
-
PopoverPrimitive.Content,
|
|
16056
|
-
{
|
|
16057
|
-
"data-slot": "popover-content",
|
|
16058
|
-
align,
|
|
16059
|
-
sideOffset,
|
|
16060
|
-
className: cn(
|
|
16061
|
-
`bg-popover text-popover-foreground data-[state=open]:animate-in
|
|
16062
|
-
data-[state=closed]:animate-out data-[state=closed]:fade-out-0
|
|
16063
|
-
data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95
|
|
16064
|
-
data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2
|
|
16065
|
-
data-[side=left]:slide-in-from-right-2
|
|
16066
|
-
data-[side=right]:slide-in-from-left-2
|
|
16067
|
-
data-[side=top]:slide-in-from-bottom-2 z-50 w-72
|
|
16068
|
-
origin-(--radix-popover-content-transform-origin) rounded-md border
|
|
16069
|
-
p-4 shadow-md outline-hidden`,
|
|
16070
|
-
className
|
|
16071
|
-
),
|
|
16072
|
-
...props
|
|
16073
|
-
}
|
|
16074
|
-
) });
|
|
16075
|
-
}
|
|
16076
|
-
|
|
16077
|
-
// ../ui/src/components/folder-filter-bar.tsx
|
|
16078
|
-
import { Fragment, jsx as jsx9, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
16079
|
-
var FolderFilterIconContext = createContext(() => /* @__PURE__ */ jsx9(Folder, { "aria-hidden": "true" }));
|
|
16080
|
-
function folderIcon(renderIcon, folder2) {
|
|
16081
|
-
return /* @__PURE__ */ jsx9(
|
|
16082
|
-
"span",
|
|
16083
|
-
{
|
|
16084
|
-
"aria-hidden": "true",
|
|
16085
|
-
className: "inline-flex size-4 shrink-0 items-center justify-center\n [&>img]:size-full [&>img]:rounded-sm [&>img]:object-contain\n [&>svg]:size-full",
|
|
16086
|
-
children: renderIcon(folder2)
|
|
16087
|
-
}
|
|
16088
|
-
);
|
|
16089
|
-
}
|
|
16090
|
-
function FolderFilterBar({
|
|
16091
|
-
allLabel = "All folders",
|
|
16092
|
-
ariaLabel = "Filter by folder",
|
|
16093
|
-
choices,
|
|
16094
|
-
onSelect,
|
|
16095
|
-
selected,
|
|
16096
|
-
total
|
|
16097
|
-
}) {
|
|
16098
|
-
const renderIcon = useContext(FolderFilterIconContext);
|
|
16099
|
-
const isSelected = (folder2) => selected.includes(folder2);
|
|
16100
|
-
const toggle = (folder2) => isSelected(folder2) ? onSelect(selected.filter((entry) => entry !== folder2)) : onSelect([...selected, folder2]);
|
|
16101
|
-
return /* @__PURE__ */ jsxs4(Popover, { children: [
|
|
16102
|
-
/* @__PURE__ */ jsx9(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs4(
|
|
16103
|
-
Button,
|
|
16104
|
-
{
|
|
16105
|
-
"aria-label": ariaLabel,
|
|
16106
|
-
className: "gap-1.5 border-[#dde1dc] bg-white text-[0.82rem]\n font-medium text-[#4a554b] hover:bg-[#f3f5f2]",
|
|
16107
|
-
size: "sm",
|
|
16108
|
-
type: "button",
|
|
16109
|
-
variant: "outline",
|
|
16110
|
-
children: [
|
|
16111
|
-
/* @__PURE__ */ jsx9(FolderSearch, { "aria-hidden": "true", className: "size-4 text-[#6c7a6d]" }),
|
|
16112
|
-
"Folder",
|
|
16113
|
-
/* @__PURE__ */ jsx9(
|
|
16114
|
-
Badge,
|
|
16115
|
-
{
|
|
16116
|
-
className: "ml-0.5 bg-[#dce8de] px-1.5 text-[#3f6048]",
|
|
16117
|
-
variant: "secondary",
|
|
16118
|
-
children: selected.length > 0 ? selected.length : total
|
|
16119
|
-
}
|
|
16120
|
-
)
|
|
16121
|
-
]
|
|
16122
|
-
}
|
|
16123
|
-
) }),
|
|
16124
|
-
/* @__PURE__ */ jsx9(
|
|
16125
|
-
PopoverContent,
|
|
16126
|
-
{
|
|
16127
|
-
align: "start",
|
|
16128
|
-
className: "w-72 overflow-hidden p-0",
|
|
16129
|
-
sideOffset: 6,
|
|
16130
|
-
children: /* @__PURE__ */ jsxs4(Command, { children: [
|
|
16131
|
-
/* @__PURE__ */ jsx9(CommandInput, { placeholder: "Search folders\u2026" }),
|
|
16132
|
-
/* @__PURE__ */ jsxs4(CommandList, { children: [
|
|
16133
|
-
/* @__PURE__ */ jsx9(CommandEmpty, { children: "No folders match" }),
|
|
16134
|
-
/* @__PURE__ */ jsx9(CommandGroup, { children: /* @__PURE__ */ jsxs4(CommandItem, { onSelect: () => onSelect([]), value: "__all__", children: [
|
|
16135
|
-
/* @__PURE__ */ jsx9(
|
|
16136
|
-
FolderSearch,
|
|
16137
|
-
{
|
|
16138
|
-
"aria-hidden": "true",
|
|
16139
|
-
className: "size-4 text-[#6c7a6d]"
|
|
16140
|
-
}
|
|
16141
|
-
),
|
|
16142
|
-
/* @__PURE__ */ jsx9("span", { children: allLabel }),
|
|
16143
|
-
/* @__PURE__ */ jsx9(
|
|
16144
|
-
"span",
|
|
16145
|
-
{
|
|
16146
|
-
className: cn(
|
|
16147
|
-
"ml-auto text-[0.75rem] font-medium",
|
|
16148
|
-
selected.length === 0 ? "text-[#3f6048]" : "text-[#6c7a6d]"
|
|
16149
|
-
),
|
|
16150
|
-
children: total
|
|
16151
|
-
}
|
|
16152
|
-
),
|
|
16153
|
-
selected.length === 0 ? /* @__PURE__ */ jsx9(Check2, { "aria-hidden": "true", className: "size-4 text-[#3f6048]" }) : null
|
|
16154
|
-
] }) }),
|
|
16155
|
-
/* @__PURE__ */ jsx9(CommandGroup, { heading: "Folders", children: choices.map((choice) => {
|
|
16156
|
-
const active = isSelected(choice.folder);
|
|
16157
|
-
return /* @__PURE__ */ jsxs4(
|
|
16158
|
-
CommandItem,
|
|
16159
|
-
{
|
|
16160
|
-
onSelect: () => toggle(choice.folder),
|
|
16161
|
-
title: choice.folder,
|
|
16162
|
-
value: choice.folder,
|
|
16163
|
-
children: [
|
|
16164
|
-
folderIcon(renderIcon, choice.folder),
|
|
16165
|
-
/* @__PURE__ */ jsx9("span", { className: "truncate", children: choice.relativePath === "" ? "This folder" : choice.label }),
|
|
16166
|
-
/* @__PURE__ */ jsx9(
|
|
16167
|
-
"span",
|
|
16168
|
-
{
|
|
16169
|
-
className: cn(
|
|
16170
|
-
"ml-auto text-[0.75rem] font-medium",
|
|
16171
|
-
active ? "text-[#3f6048]" : "text-[#6c7a6d]"
|
|
16172
|
-
),
|
|
16173
|
-
children: choice.count
|
|
16174
|
-
}
|
|
16175
|
-
),
|
|
16176
|
-
active ? /* @__PURE__ */ jsx9(
|
|
16177
|
-
Check2,
|
|
16178
|
-
{
|
|
16179
|
-
"aria-hidden": "true",
|
|
16180
|
-
className: "size-4 shrink-0 text-[#3f6048]"
|
|
16181
|
-
}
|
|
16182
|
-
) : null
|
|
16183
|
-
]
|
|
16184
|
-
},
|
|
16185
|
-
choice.folder
|
|
16186
|
-
);
|
|
16187
|
-
}) })
|
|
16188
|
-
] })
|
|
16189
|
-
] })
|
|
16190
|
-
}
|
|
16191
|
-
)
|
|
16192
|
-
] });
|
|
16193
|
-
}
|
|
16194
|
-
|
|
16195
|
-
// ../ui/src/hooks/use-folder-filter.ts
|
|
16196
|
-
import { useCallback as useCallback2, useMemo, useState as useState3 } from "react";
|
|
16197
|
-
|
|
16198
|
-
// ../ui/src/lib/folder-filter.ts
|
|
16199
|
-
function normalized(value) {
|
|
16200
|
-
return value.replaceAll("\\", "/").replace(/\/+$/, "");
|
|
16201
|
-
}
|
|
16202
|
-
function folderFilterRelativePath(folder2, rootFolder) {
|
|
16203
|
-
const root = normalized(rootFolder);
|
|
16204
|
-
const candidate = normalized(folder2);
|
|
16205
|
-
if (!root || !candidate) return null;
|
|
16206
|
-
if (candidate === root) return "";
|
|
16207
|
-
if (!candidate.startsWith(`${root}/`)) return null;
|
|
16208
|
-
const relative = candidate.slice(root.length + 1);
|
|
16209
|
-
if (!relative) return null;
|
|
16210
|
-
if (relative.split("/").some((segment) => segment === ".." || segment === "."))
|
|
16211
|
-
return null;
|
|
16212
|
-
return relative;
|
|
16213
|
-
}
|
|
16214
|
-
function rootLabel(rootFolder) {
|
|
16215
|
-
return normalized(rootFolder).split("/").filter((segment) => Boolean(segment)).at(-1) ?? "This folder";
|
|
16216
|
-
}
|
|
16217
|
-
function baseName(value) {
|
|
16218
|
-
return normalized(value).split("/").filter((segment) => Boolean(segment)).at(-1) ?? value;
|
|
16219
|
-
}
|
|
16220
|
-
function folderFilterChoices(items2, rootFolder, getFolder, options) {
|
|
16221
|
-
const counts = /* @__PURE__ */ new Map();
|
|
16222
|
-
for (const item of items2) {
|
|
16223
|
-
const folder2 = getFolder(item);
|
|
16224
|
-
if (!folder2) continue;
|
|
16225
|
-
const contained = folderFilterRelativePath(folder2, rootFolder);
|
|
16226
|
-
if (contained === null && !options?.allowOutside) continue;
|
|
16227
|
-
counts.set(folder2, (counts.get(folder2) ?? 0) + 1);
|
|
16228
|
-
}
|
|
16229
|
-
const choices = [];
|
|
16230
|
-
for (const [folder2, count] of counts) {
|
|
16231
|
-
const contained = folderFilterRelativePath(folder2, rootFolder);
|
|
16232
|
-
const relativePath = contained ?? (options?.allowOutside ? baseName(folder2) : "");
|
|
16233
|
-
choices.push({
|
|
16234
|
-
count,
|
|
16235
|
-
folder: folder2,
|
|
16236
|
-
label: relativePath || rootLabel(rootFolder),
|
|
16237
|
-
relativePath
|
|
16238
|
-
});
|
|
16239
|
-
}
|
|
16240
|
-
return choices.sort((a, b) => {
|
|
16241
|
-
if (a.relativePath === "") return -1;
|
|
16242
|
-
if (b.relativePath === "") return 1;
|
|
16243
|
-
return a.relativePath.localeCompare(b.relativePath);
|
|
16244
|
-
});
|
|
16245
|
-
}
|
|
16246
|
-
function matchTarget(folder2, target, mode) {
|
|
16247
|
-
if (!folder2) return false;
|
|
16248
|
-
const candidate = normalized(folder2);
|
|
16249
|
-
const goal = normalized(target);
|
|
16250
|
-
if (mode === "subtree")
|
|
16251
|
-
return candidate === goal || candidate.startsWith(`${goal}/`);
|
|
16252
|
-
return candidate === goal;
|
|
16253
|
-
}
|
|
16254
|
-
function folderFilterMatches(folder2, selected, mode = "exact") {
|
|
16255
|
-
if (selected === null || selected === "") return true;
|
|
16256
|
-
if (Array.isArray(selected)) {
|
|
16257
|
-
if (selected.length === 0) return true;
|
|
16258
|
-
return selected.some((entry) => folderFilterMatches(folder2, entry, mode));
|
|
16259
|
-
}
|
|
16260
|
-
return matchTarget(folder2, selected, mode);
|
|
16261
|
-
}
|
|
16262
|
-
function applyFolderFilter(input) {
|
|
16263
|
-
const {
|
|
16264
|
-
allowOutside,
|
|
16265
|
-
getFolder,
|
|
16266
|
-
items: items2,
|
|
16267
|
-
mode = "exact",
|
|
16268
|
-
rootFolder,
|
|
16269
|
-
selected
|
|
16270
|
-
} = input;
|
|
16271
|
-
const choices = folderFilterChoices(items2, rootFolder, getFolder, {
|
|
16272
|
-
allowOutside
|
|
16273
|
-
});
|
|
16274
|
-
const rawEntries = selected === null ? [] : Array.isArray(selected) ? selected : [selected];
|
|
16275
|
-
const effectiveSelected = rawEntries.filter(
|
|
16276
|
-
(entry) => items2.some((item) => folderFilterMatches(getFolder(item), entry, mode))
|
|
16277
|
-
);
|
|
16278
|
-
const visibleItems = effectiveSelected.length === 0 ? [...items2] : items2.filter(
|
|
16279
|
-
(item) => folderFilterMatches(getFolder(item), effectiveSelected, mode)
|
|
16280
|
-
);
|
|
16281
|
-
return { choices, effectiveSelected, total: items2.length, visibleItems };
|
|
16282
|
-
}
|
|
16283
|
-
|
|
16284
|
-
// ../ui/src/hooks/use-folder-filter.ts
|
|
16285
|
-
function useFolderFilter(items2, options) {
|
|
16286
|
-
const { allowOutside, getFolder, mode, rootFolder } = options;
|
|
16287
|
-
const [selected, setSelectedState] = useState3(() => {
|
|
16288
|
-
const initial = options.initialFolder;
|
|
16289
|
-
if (initial === null || initial === void 0) return [];
|
|
16290
|
-
return Array.isArray(initial) ? initial : [initial];
|
|
16291
|
-
});
|
|
16292
|
-
const setSelected = useCallback2((folder2) => {
|
|
16293
|
-
setSelectedState(
|
|
16294
|
-
folder2 === null || folder2 === void 0 ? [] : Array.isArray(folder2) ? folder2 : [folder2]
|
|
16295
|
-
);
|
|
16296
|
-
}, []);
|
|
16297
|
-
const toggle = useCallback2((folder2) => {
|
|
16298
|
-
setSelectedState(
|
|
16299
|
-
(current) => current.includes(folder2) ? current.filter((entry) => entry !== folder2) : [...current, folder2]
|
|
16300
|
-
);
|
|
16301
|
-
}, []);
|
|
16302
|
-
const reset = useCallback2(() => setSelectedState([]), []);
|
|
16303
|
-
const result = useMemo(
|
|
16304
|
-
() => applyFolderFilter({
|
|
16305
|
-
allowOutside,
|
|
16306
|
-
getFolder,
|
|
16307
|
-
items: items2,
|
|
16308
|
-
mode,
|
|
16309
|
-
rootFolder,
|
|
16310
|
-
selected
|
|
16311
|
-
}),
|
|
16312
|
-
[allowOutside, getFolder, items2, mode, rootFolder, selected]
|
|
16313
|
-
);
|
|
16314
|
-
return {
|
|
16315
|
-
...result,
|
|
16316
|
-
selected,
|
|
16317
|
-
setSelected,
|
|
16318
|
-
toggle,
|
|
16319
|
-
reset
|
|
16320
|
-
};
|
|
16321
|
-
}
|
|
16322
|
-
|
|
16323
15867
|
export {
|
|
16324
15868
|
EntityPage,
|
|
16325
15869
|
EntityStatus,
|
|
16326
15870
|
EntityError,
|
|
16327
15871
|
CopyContextButton,
|
|
16328
15872
|
FilePreview,
|
|
16329
|
-
FilePreviewList
|
|
16330
|
-
FolderFilterBar,
|
|
16331
|
-
useFolderFilter
|
|
15873
|
+
FilePreviewList
|
|
16332
15874
|
};
|
package/dist/hooks.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
|
|
4
|
+
/** Host boundary. The host and plugin must resolve this module once. */
|
|
5
|
+
declare function FolderPathProvider({ folder, children, }: {
|
|
6
|
+
folder: string;
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
}): react.FunctionComponentElement<react.ProviderProps<string | undefined>>;
|
|
9
|
+
/** Current viewed folder. This is not a filter selection or a permission check. */
|
|
10
|
+
declare function useFolderPath(): string;
|
|
11
|
+
|
|
12
|
+
export { FolderPathProvider, useFolderPath };
|
package/dist/hooks.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import "./chunk-MLKGABMK.js";
|
|
2
|
+
|
|
3
|
+
// src/hooks.ts
|
|
4
|
+
import { createContext, createElement, useContext } from "react";
|
|
5
|
+
var FolderPathContext = createContext(void 0);
|
|
6
|
+
function FolderPathProvider({
|
|
7
|
+
folder,
|
|
8
|
+
children
|
|
9
|
+
}) {
|
|
10
|
+
return createElement(FolderPathContext.Provider, { value: folder }, children);
|
|
11
|
+
}
|
|
12
|
+
function useFolderPath() {
|
|
13
|
+
const folder = useContext(FolderPathContext);
|
|
14
|
+
if (folder === void 0) {
|
|
15
|
+
throw new Error("useFolderPath must be used inside FolderPathProvider");
|
|
16
|
+
}
|
|
17
|
+
return folder;
|
|
18
|
+
}
|
|
19
|
+
export {
|
|
20
|
+
FolderPathProvider,
|
|
21
|
+
useFolderPath
|
|
22
|
+
};
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export { CopyContextButton, FilePreview, FilePreviewList,
|
|
1
|
+
export { CopyContextButton, FilePreview, FilePreviewList, PluginPage, PluginPageError, PluginPageStatus } from './page.js';
|
|
2
2
|
export { FolderPluginClient, FolderPluginHostActions, FolderPluginViewProps, folderPathId } from './client.js';
|
|
3
3
|
export { ApiError, ApiErrorCode, ApiRouteHandle, ApiRouteSpec, apiError, jsonError, jsonResponse, parseJsonBody, readBoundedBody, runApiRoute, sameOrigin } from './endpoint.js';
|
|
4
4
|
export { FolderPluginContext, FolderPluginData, FolderPluginFailure, FolderPluginInitFile, FolderPluginInitResult, FolderPluginServer } from './server.js';
|
|
5
|
-
export { FolderPluginDataset, FolderPluginDetection, FolderPluginId, FolderPluginManifest, FolderPluginPayload, FolderPluginPayloadError, isPluginPayloadError } from './types.js';
|
|
5
|
+
export { FolderPluginDataset, FolderPluginDetection, FolderPluginIcon, FolderPluginId, FolderPluginManifest, FolderPluginPayload, FolderPluginPayloadError, isPluginPayloadError } from './types.js';
|
|
6
6
|
import 'react';
|
|
7
7
|
import 'class-variance-authority/types';
|
|
8
8
|
import 'class-variance-authority';
|
package/dist/index.js
CHANGED
|
@@ -14,10 +14,8 @@ import {
|
|
|
14
14
|
EntityPage,
|
|
15
15
|
EntityStatus,
|
|
16
16
|
FilePreview,
|
|
17
|
-
FilePreviewList
|
|
18
|
-
|
|
19
|
-
useFolderFilter
|
|
20
|
-
} from "./chunk-454D7WI6.js";
|
|
17
|
+
FilePreviewList
|
|
18
|
+
} from "./chunk-FLSLPC4P.js";
|
|
21
19
|
import {
|
|
22
20
|
folderPathId
|
|
23
21
|
} from "./chunk-STR4VH4C.js";
|
|
@@ -33,7 +31,6 @@ export {
|
|
|
33
31
|
CopyContextButton,
|
|
34
32
|
FilePreview,
|
|
35
33
|
FilePreviewList,
|
|
36
|
-
FolderFilterBar,
|
|
37
34
|
FolderPluginFailure,
|
|
38
35
|
EntityPage as PluginPage,
|
|
39
36
|
EntityError as PluginPageError,
|
|
@@ -46,6 +43,5 @@ export {
|
|
|
46
43
|
parseJsonBody,
|
|
47
44
|
readBoundedBody,
|
|
48
45
|
runApiRoute,
|
|
49
|
-
sameOrigin
|
|
50
|
-
useFolderFilter
|
|
46
|
+
sameOrigin
|
|
51
47
|
};
|
package/dist/page.d.ts
CHANGED
|
@@ -20,7 +20,7 @@ declare function EntityPage({ header, extra, children, }: {
|
|
|
20
20
|
*/
|
|
21
21
|
declare function EntityStatus({ children }: {
|
|
22
22
|
children: ReactNode;
|
|
23
|
-
}): number | bigint | boolean |
|
|
23
|
+
}): number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | react.ReactPortal | react.ReactElement<unknown, string | react.JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | react.JSX.Element | null | undefined;
|
|
24
24
|
/**
|
|
25
25
|
* An error block: plain strings render as a destructive line with an
|
|
26
26
|
* optional retry button; richer nodes pass through untouched.
|
|
@@ -28,10 +28,10 @@ declare function EntityStatus({ children }: {
|
|
|
28
28
|
declare function EntityError({ error, onRetry, }: {
|
|
29
29
|
error: ReactNode;
|
|
30
30
|
onRetry?: () => void;
|
|
31
|
-
}): number | bigint | boolean |
|
|
31
|
+
}): number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | react.ReactPortal | react.ReactElement<unknown, string | react.JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | react.JSX.Element | null | undefined;
|
|
32
32
|
|
|
33
33
|
declare const buttonVariants: (props?: ({
|
|
34
|
-
variant?: "default" | "destructive" | "outline" | "secondary" | "ghost" |
|
|
34
|
+
variant?: "link" | "default" | "destructive" | "outline" | "secondary" | "ghost" | null | undefined;
|
|
35
35
|
size?: "default" | "xs" | "sm" | "lg" | "icon" | "icon-xs" | "icon-sm" | "icon-lg" | null | undefined;
|
|
36
36
|
} & class_variance_authority_types.ClassProp) | undefined) => string;
|
|
37
37
|
declare function Button({ className, variant, size, asChild, ...props }: react.ComponentProps<"button"> & VariantProps<typeof buttonVariants> & {
|
|
@@ -80,125 +80,4 @@ declare function FilePreviewList({ paths }: {
|
|
|
80
80
|
paths: string[];
|
|
81
81
|
}): react.JSX.Element;
|
|
82
82
|
|
|
83
|
-
|
|
84
|
-
* Generalized folder filtering for lists of items that carry an owning
|
|
85
|
-
* folder path.
|
|
86
|
-
*
|
|
87
|
-
* Pure string/array logic — no React, no DOM, no `node:` builtins — so the
|
|
88
|
-
* exact same helpers power web chips, folder-plugin views, and CLI
|
|
89
|
-
* filtering. The model mirrors the mail plugin's draft selector but is
|
|
90
|
-
* accessor-driven: you hand over your items, a function that reads each
|
|
91
|
-
* item's owning folder, and the viewed root folder; you get back the
|
|
92
|
-
* distinct folder choices (root first, then descendants by relative path,
|
|
93
|
-
* each with a count) and a predicate that decides which items a selection
|
|
94
|
-
* keeps.
|
|
95
|
-
*
|
|
96
|
-
* CLI example (no React):
|
|
97
|
-
*
|
|
98
|
-
* ```ts
|
|
99
|
-
* import {
|
|
100
|
-
* folderFilterChoices,
|
|
101
|
-
* folderFilterMatches,
|
|
102
|
-
* } from "@raggle-ai/ui/lib/folder-filter"
|
|
103
|
-
*
|
|
104
|
-
* const choices = folderFilterChoices(items, root, (item) => item.folder)
|
|
105
|
-
* const visible = items.filter((item) =>
|
|
106
|
-
* folderFilterMatches(item.folder, flags.folder, "subtree"),
|
|
107
|
-
* )
|
|
108
|
-
* ```
|
|
109
|
-
*/
|
|
110
|
-
/** How a selected folder applies to an item's owning folder. */
|
|
111
|
-
type FolderFilterMode = "exact" | "subtree";
|
|
112
|
-
/**
|
|
113
|
-
* One clickable chip: a distinct owning folder in the item list. `folder`
|
|
114
|
-
* is the full owning path and the exact filter key (duplicate leaf names
|
|
115
|
-
* stay distinct); `label` is the short display text (basename for the
|
|
116
|
-
* root, relative path for descendants).
|
|
117
|
-
*/
|
|
118
|
-
type FolderFilterChoice = {
|
|
119
|
-
/** Exact owning folder path — the filter key. */
|
|
120
|
-
folder: string;
|
|
121
|
-
/** Number of items owned by this folder. */
|
|
122
|
-
count: number;
|
|
123
|
-
/** Short display label: basename for the root, relative path for descendants. */
|
|
124
|
-
label: string;
|
|
125
|
-
/** Path relative to the viewed root; "" for the root itself. */
|
|
126
|
-
relativePath: string;
|
|
127
|
-
};
|
|
128
|
-
/**
|
|
129
|
-
* A selection for folder filtering: a single owning folder, several
|
|
130
|
-
* (multi-select — an item passes when any of them matches), or null/
|
|
131
|
-
* empty for "all items". Single-string callers keep working unchanged.
|
|
132
|
-
*/
|
|
133
|
-
type FolderSelection = string | readonly string[] | null;
|
|
134
|
-
|
|
135
|
-
/**
|
|
136
|
-
* Multi-select folder filter as a single "Folder (count)" button. The
|
|
137
|
-
* count badge shows how many folders are selected, or the total when
|
|
138
|
-
* nothing is filtered. The popover holds a searchable command list with
|
|
139
|
-
* an "All folders" row that clears back to everything; every folder row
|
|
140
|
-
* toggles into the selection in real time.
|
|
141
|
-
*
|
|
142
|
-
* Rows are portal-mounted on open (like this repo's Select), so closed
|
|
143
|
-
* dropdown content is not in the SSR/tree — the trigger carries the
|
|
144
|
-
* accessible count instead.
|
|
145
|
-
*/
|
|
146
|
-
declare function FolderFilterBar({ allLabel, ariaLabel, choices, onSelect, selected, total, }: {
|
|
147
|
-
/** Label of the row that clears the selection. */
|
|
148
|
-
allLabel?: string;
|
|
149
|
-
/** Accessible name for the filter trigger. */
|
|
150
|
-
ariaLabel?: string;
|
|
151
|
-
choices: FolderFilterChoice[];
|
|
152
|
-
/** All currently selected owning folders; pass [] to show everything. */
|
|
153
|
-
onSelect: (folders: readonly string[]) => void;
|
|
154
|
-
/** Currently selected owning folders; empty means "all". */
|
|
155
|
-
selected: readonly string[];
|
|
156
|
-
/** Count shown on the trigger while nothing is selected. */
|
|
157
|
-
total: number;
|
|
158
|
-
}): react.JSX.Element;
|
|
159
|
-
|
|
160
|
-
type UseFolderFilterOptions<T> = {
|
|
161
|
-
/** Owning folder of each item; null when the item has none. */
|
|
162
|
-
getFolder: (item: T) => string | null;
|
|
163
|
-
/** "exact" keeps the selected folder's items only; "subtree" also keeps descendant items. */
|
|
164
|
-
mode?: FolderFilterMode;
|
|
165
|
-
/** Include ancestor/outside folders as chips (see `folderFilterChoices`). */
|
|
166
|
-
allowOutside?: boolean;
|
|
167
|
-
/** Folder everything is shown relative to (the viewed root). */
|
|
168
|
-
rootFolder: string;
|
|
169
|
-
/** Initial selection (owning folder paths); a selection with no items falls back to all. */
|
|
170
|
-
initialFolder?: FolderSelection;
|
|
171
|
-
};
|
|
172
|
-
type UseFolderFilterResult<T> = {
|
|
173
|
-
/** Distinct owning-folder choices with counts, root first. */
|
|
174
|
-
choices: FolderFilterChoice[];
|
|
175
|
-
/**
|
|
176
|
-
* Selection entries that still match items. Empty means "all items" —
|
|
177
|
-
* either nothing is selected or every selected folder lost its items.
|
|
178
|
-
*/
|
|
179
|
-
effectiveSelected: readonly string[];
|
|
180
|
-
/** Raw selection state; entries whose folder has no items left may be stale. */
|
|
181
|
-
selected: readonly string[];
|
|
182
|
-
/**
|
|
183
|
-
* Replace the selection. Pass a single folder, an array of folders (an
|
|
184
|
-
* item passes when any of them matches), or null/[] to show everything.
|
|
185
|
-
*/
|
|
186
|
-
setSelected: (folder: FolderSelection) => void;
|
|
187
|
-
/** Toggle one owning folder in/out of the selection. */
|
|
188
|
-
toggle: (folder: string) => void;
|
|
189
|
-
/** Clear the selection back to "all items". */
|
|
190
|
-
reset: () => void;
|
|
191
|
-
/** Number of items before filtering — shown on the "All" chip. */
|
|
192
|
-
total: number;
|
|
193
|
-
/** Items after applying the effective selection. */
|
|
194
|
-
visibleItems: T[];
|
|
195
|
-
};
|
|
196
|
-
/**
|
|
197
|
-
* Folder-filter state for a plugin view: pass the items and a folder
|
|
198
|
-
* accessor, get the choices, the reconciled (multi-)selection, and the
|
|
199
|
-
* filtered `visibleItems` in one place. Recomputes only when the items,
|
|
200
|
-
* accessor, root, mode, or selection change.
|
|
201
|
-
*/
|
|
202
|
-
declare function useFolderFilter<T>(items: readonly T[], options: UseFolderFilterOptions<T>): UseFolderFilterResult<T>;
|
|
203
|
-
|
|
204
|
-
export { CopyContextButton, FilePreview, FilePreviewList, FolderFilterBar, type FolderFilterChoice, type FolderFilterMode, type FolderSelection, EntityPage as PluginPage, EntityError as PluginPageError, EntityStatus as PluginPageStatus, useFolderFilter };
|
|
83
|
+
export { CopyContextButton, FilePreview, FilePreviewList, EntityPage as PluginPage, EntityError as PluginPageError, EntityStatus as PluginPageStatus };
|
package/dist/page.js
CHANGED
|
@@ -4,10 +4,8 @@ import {
|
|
|
4
4
|
EntityPage,
|
|
5
5
|
EntityStatus,
|
|
6
6
|
FilePreview,
|
|
7
|
-
FilePreviewList
|
|
8
|
-
|
|
9
|
-
useFolderFilter
|
|
10
|
-
} from "./chunk-454D7WI6.js";
|
|
7
|
+
FilePreviewList
|
|
8
|
+
} from "./chunk-FLSLPC4P.js";
|
|
11
9
|
import "./chunk-STR4VH4C.js";
|
|
12
10
|
import "./chunk-YLSYYX2L.js";
|
|
13
11
|
import "./chunk-MLKGABMK.js";
|
|
@@ -15,9 +13,7 @@ export {
|
|
|
15
13
|
CopyContextButton,
|
|
16
14
|
FilePreview,
|
|
17
15
|
FilePreviewList,
|
|
18
|
-
FolderFilterBar,
|
|
19
16
|
EntityPage as PluginPage,
|
|
20
17
|
EntityError as PluginPageError,
|
|
21
|
-
EntityStatus as PluginPageStatus
|
|
22
|
-
useFolderFilter
|
|
18
|
+
EntityStatus as PluginPageStatus
|
|
23
19
|
};
|
package/dist/types.d.ts
CHANGED
|
@@ -11,9 +11,16 @@ type ContentIssue = {
|
|
|
11
11
|
* invalidate content — the file still detects as valid. */
|
|
12
12
|
severity?: "warning";
|
|
13
13
|
};
|
|
14
|
+
/** Plugin-owned SVG path data. No React or page imports are needed for tabs. */
|
|
15
|
+
type FolderPluginIcon = {
|
|
16
|
+
/** Paths use a 24 × 24 view box and the navigation text color. */
|
|
17
|
+
paths: string[];
|
|
18
|
+
};
|
|
14
19
|
type FolderPluginManifest = {
|
|
15
20
|
/** Stable identifier used in routes, URLs, and registries. Never a URL segment turned into an import path. */
|
|
16
21
|
id: FolderPluginId;
|
|
22
|
+
/** Optional plugin-owned navigation icon. Omit for a text-only tab. */
|
|
23
|
+
icon?: FolderPluginIcon;
|
|
17
24
|
/** Navigation label shown in the folder shell. */
|
|
18
25
|
label: string;
|
|
19
26
|
};
|
|
@@ -78,4 +85,4 @@ type FolderPluginPayload<T> = {
|
|
|
78
85
|
/** True when the decoded data is an in-band error payload. */
|
|
79
86
|
declare function isPluginPayloadError(data: unknown): data is FolderPluginPayloadError;
|
|
80
87
|
|
|
81
|
-
export { type ContentIssue, type FolderPluginDataset, type FolderPluginDetection, type FolderPluginId, type FolderPluginManifest, type FolderPluginPayload, type FolderPluginPayloadError, isPluginPayloadError };
|
|
88
|
+
export { type ContentIssue, type FolderPluginDataset, type FolderPluginDetection, type FolderPluginIcon, type FolderPluginId, type FolderPluginManifest, type FolderPluginPayload, type FolderPluginPayloadError, isPluginPayloadError };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json.schemastore.org/package.json",
|
|
3
3
|
"name": "kennel-plugins",
|
|
4
|
-
"version": "0.1.
|
|
4
|
+
"version": "0.1.4",
|
|
5
5
|
"description": "Small shared contract for trusted folder view plugins in the Kennel web viewer.",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"license": "MIT",
|
|
@@ -32,6 +32,10 @@
|
|
|
32
32
|
"types": "./dist/endpoint.d.ts",
|
|
33
33
|
"import": "./dist/endpoint.js"
|
|
34
34
|
},
|
|
35
|
+
"./hooks": {
|
|
36
|
+
"types": "./dist/hooks.d.ts",
|
|
37
|
+
"import": "./dist/hooks.js"
|
|
38
|
+
},
|
|
35
39
|
"./page": {
|
|
36
40
|
"types": "./dist/page.d.ts",
|
|
37
41
|
"import": "./dist/page.js"
|