@knpkv/rly 0.11.0 → 0.12.0
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/README.md +6 -1
- package/dist/base.css +2 -2
- package/dist/components.css +2 -2
- package/dist/diff/bounded/index.js.map +1 -1
- package/dist/diff/index.js.map +1 -1
- package/dist/diff/patch/index.js.map +1 -1
- package/dist/generated-tokens.css +2 -0
- package/dist/patterns-DPd5YlSW.js.map +1 -1
- package/dist/primitives-CgvvYKjR.js.map +1 -1
- package/dist/workbench-CHCnYW3G.js.map +1 -1
- package/package.json +2 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"workbench-CHCnYW3G.js","names":["root","header","notice","empty","group","root","style","styles","style","styles","styles","requireText","cssClass","classNames","DiffFileTree_module_default","DiffHeader_module_default","DiffWorkbench_module_default","style$2","name","contentLabel","content","visibleGitPath","path","segment","wrappableGitPath","index","requireGitPath","label","changeIcons","FilePlus2","FileX2","FilePenLine","FileSymlink","validateInventory","ids","file","data","id","compactDirectory","node","child","buildFileTree","leaves","directories","treeFile","files","depth","grouped","directoryAncestors","segments","DiffFileTree","props","visibleHeading","heading","selectedFileId","headingId","useId","indexedCount","totalCount","tree","useMemo","collapsedDirectories","setCollapsedDirectories","useState","selectedPath","ancestors","current","renderNodes","nodes","isSelected","ChangeIcon","exceptionalContent","onSelectedFileChange","LoaderCircle","CircleAlert","expanded","next","className","style$1","findingFilters","layouts","titleCase","value","validateCounts","DiffHeader","selectedFileLabel","progressId","layout","option","onLayoutChange","isWrapped","onWrapChange","findingFilter","filter","onFindingFilterChange","style","validateFindings","finding","findings","DiffWorkbench","visibleLabel","visibleScopeLabel","scope","visibleInventoryLabel","inventoryLabel","visibleViewerLabel","viewerLabel","visibleFindingsLabel","findingsLabel","onShowAllFiles","header","inventory","statusNotice","viewer","emptyFindings"],"sources":["../src/diff/DiffFileTree.module.css","../src/diff/DiffHeader.module.css","../src/diff/DiffWorkbench.module.css","../src/diff/DiffFileTree.tsx","../src/diff/DiffHeader.tsx","../src/diff/DiffWorkbench.tsx"],"sourcesContent":["@layer rly.components {\n .root {\n background: var(--rly-color-surface-1);\n border: 1px solid var(--rly-color-border-1);\n border-radius: var(--rly-radius-group);\n container-type: inline-size;\n display: grid;\n /* One bounded track: an implicit auto track can't shrink below its content, so it overflowed at 320. */\n grid-template-columns: minmax(var(--rly-space-0), 1fr);\n min-inline-size: var(--rly-space-0);\n overflow: hidden;\n }\n\n /* Heading and count share a row while they fit; the count wraps below in a narrow tree. */\n .header {\n align-items: baseline;\n display: flex;\n flex-wrap: wrap;\n gap: var(--rly-space-4) var(--rly-space-16);\n justify-content: space-between;\n padding: var(--rly-space-20);\n }\n\n .header > span {\n display: grid;\n gap: var(--rly-space-2);\n min-inline-size: var(--rly-space-0);\n }\n\n .header h2 {\n color: var(--rly-color-text-1);\n font: var(--rly-type-card-title-weight) var(--rly-type-card-title-size) / var(--rly-type-card-title-line-height)\n var(--rly-type-card-title-font);\n letter-spacing: var(--rly-type-card-title-tracking);\n margin: var(--rly-space-0);\n overflow-wrap: break-word;\n }\n\n .notice,\n .empty,\n .error,\n .previousPath {\n color: var(--rly-color-text-2);\n font: var(--rly-type-meta-weight) var(--rly-type-meta-size) / var(--rly-type-meta-line-height)\n var(--rly-type-meta-font);\n }\n\n .count {\n color: var(--rly-color-text-2);\n font: var(--rly-type-meta-weight) var(--rly-type-meta-size) / var(--rly-type-meta-line-height)\n var(--rly-type-meta-font);\n white-space: nowrap;\n }\n\n .notice,\n .empty,\n .error {\n border-block-start: 1px solid var(--rly-color-border-1);\n margin: var(--rly-space-0);\n padding: var(--rly-space-12) var(--rly-space-20);\n }\n\n .error {\n background: var(--rly-color-held-tint);\n display: grid;\n gap: var(--rly-space-2);\n }\n\n .error strong {\n color: var(--rly-color-text-1);\n }\n\n .list {\n border-block-start: 1px solid var(--rly-color-border-1);\n list-style: none;\n margin: var(--rly-space-0);\n max-block-size: 34rem;\n overflow: auto;\n padding: var(--rly-space-0);\n scrollbar-gutter: stable;\n }\n\n .list li:not(.directory) {\n contain: content;\n contain-intrinsic-block-size: 40px;\n }\n\n .group {\n list-style: none;\n margin: var(--rly-space-0);\n padding: var(--rly-space-0);\n }\n\n .group > li {\n position: relative;\n }\n\n .group > li::before {\n block-size: 20px;\n border-block-end: 1px solid var(--rly-color-border-2);\n border-inline-start: 1px solid var(--rly-color-border-2);\n content: \"\";\n inline-size: var(--rly-space-12);\n inset-block-start: var(--rly-space-0);\n inset-inline-start: var(--rly-space-0);\n pointer-events: none;\n position: absolute;\n z-index: 1;\n }\n\n .group > li:not(:last-child)::after {\n border-inline-start: 1px solid var(--rly-color-border-2);\n content: \"\";\n inset-block: 20px var(--rly-space-0);\n inset-inline-start: var(--rly-space-0);\n pointer-events: none;\n position: absolute;\n z-index: 1;\n }\n\n .directoryButton {\n align-items: center;\n background: transparent;\n border: 0;\n border-block-end: 1px solid var(--rly-color-border-1);\n color: var(--rly-color-text-1);\n cursor: pointer;\n display: grid;\n gap: var(--rly-space-8);\n grid-template-columns: var(--rly-space-12) minmax(var(--rly-space-0), 1fr) auto;\n inline-size: 100%;\n min-block-size: var(--rly-space-32);\n padding: var(--rly-space-8) var(--rly-space-12);\n text-align: start;\n }\n\n .directoryButton:hover {\n background: var(--rly-color-surface-2);\n }\n\n .directoryButton:focus-visible {\n outline: 3px solid var(--rly-color-focus);\n outline-offset: -3px;\n }\n\n .chevron {\n block-size: var(--rly-space-8);\n border-block-end: 1.5px solid currentcolor; /* stripe-ok: drawn chevron, two edges of a rotated square */\n border-inline-end: 1.5px solid currentcolor; /* stripe-ok: drawn chevron, mirrors in right-to-left text */\n inline-size: var(--rly-space-8);\n justify-self: center;\n /* --rly-diff-tree-turn is 1 in left-to-right text and -1 in right-to-left; see below. */\n transform: rotate(calc(45deg * var(--rly-diff-tree-turn, 1)))\n translate(calc(-1px * var(--rly-diff-tree-turn, 1)), -1px);\n transition: transform var(--rly-motion-fast-duration) var(--rly-motion-fast-easing);\n }\n\n .directoryButton[aria-expanded=\"false\"] .chevron {\n transform: rotate(calc(-45deg * var(--rly-diff-tree-turn, 1)));\n }\n\n /*\n * In right-to-left text the edges sit on the left, so the turns mirror: down when open, left when\n * shut. Each dir attribute sets the sign and the nearest one is inherited, so an LTR tree inside an\n * RTL page turns the LTR way. (The build lowers :dir() to a :lang() list, so it cannot be used.)\n */\n [dir=\"rtl\"] {\n --rly-diff-tree-turn: -1;\n }\n\n [dir=\"ltr\"] {\n --rly-diff-tree-turn: 1;\n }\n\n .directoryName {\n font: var(--rly-type-code-weight) var(--rly-type-code-size) / var(--rly-type-code-line-height)\n var(--rly-type-code-font);\n min-inline-size: var(--rly-space-0);\n overflow-wrap: break-word;\n }\n\n .directoryCount {\n color: var(--rly-color-text-3);\n font: var(--rly-type-meta-weight) var(--rly-type-meta-size) / var(--rly-type-meta-line-height)\n var(--rly-type-meta-font);\n font-variant-numeric: tabular-nums;\n }\n\n .file {\n align-items: center;\n background: transparent;\n border: 0;\n border-block-end: 1px solid var(--rly-color-border-1);\n color: inherit;\n cursor: pointer;\n display: grid;\n gap: var(--rly-space-8);\n grid-template-columns: minmax(var(--rly-space-0), 1fr) auto;\n inline-size: 100%;\n min-block-size: 40px;\n padding: var(--rly-space-6) var(--rly-space-12);\n text-align: start;\n }\n\n .file:hover {\n background: var(--rly-color-surface-2);\n }\n\n .file[aria-current=\"true\"] {\n background: var(--rly-color-surface-3);\n box-shadow: inset 0 0 0 1px var(--rly-color-border-2);\n }\n\n .file:focus-visible {\n outline: 3px solid var(--rly-color-focus);\n outline-offset: -3px;\n }\n\n .pathBlock {\n display: grid;\n min-inline-size: var(--rly-space-0);\n }\n\n /* A path is the file's identity: it wraps after a slash (or, for one long name, inside it), never ellipsised. */\n .path,\n .previousPath {\n min-inline-size: var(--rly-space-0);\n overflow-wrap: break-word;\n }\n\n .path {\n color: var(--rly-color-text-1);\n font: var(--rly-type-code-weight) var(--rly-type-code-size) / var(--rly-type-code-line-height)\n var(--rly-type-code-font);\n }\n\n .previousPath {\n text-decoration: line-through;\n }\n\n .statusIcons {\n align-items: center;\n color: var(--rly-color-text-2);\n display: inline-flex;\n gap: var(--rly-space-4);\n }\n\n .statusIcon,\n .statusIcon svg {\n block-size: var(--rly-space-16);\n inline-size: var(--rly-space-16);\n }\n .statusIcon svg {\n display: block;\n }\n\n .loadingIcon {\n animation: rly-diff-file-tree-spin 800ms linear infinite;\n }\n\n @keyframes rly-diff-file-tree-spin {\n to {\n transform: rotate(360deg);\n }\n }\n\n @container (max-width: 24rem) {\n .header {\n align-items: start;\n }\n\n .file {\n grid-template-columns: minmax(var(--rly-space-0), 1fr) auto;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .chevron,\n .loadingIcon {\n animation: none;\n transition: none;\n }\n }\n}\n","@layer rly.components {\n .root {\n background: var(--rly-color-surface-1);\n border: 1px solid var(--rly-color-border-1);\n border-radius: var(--rly-radius-group);\n container-type: inline-size;\n display: grid;\n min-inline-size: var(--rly-space-0);\n overflow: hidden;\n }\n\n /* Thesis and progress side by side; a container query below stacks them. A container cannot\n query itself, so the layout lives on this child, not on .root. */\n .summary {\n display: grid;\n grid-template-columns: minmax(var(--rly-space-0), 1fr) auto;\n min-inline-size: var(--rly-space-0);\n }\n\n .thesis {\n display: grid;\n grid-template-columns: minmax(var(--rly-space-0), 1fr);\n min-inline-size: var(--rly-space-0);\n gap: var(--rly-space-4);\n padding: var(--rly-space-24);\n }\n\n .thesis p,\n .progressCopy {\n color: var(--rly-color-text-2);\n font: var(--rly-type-meta-weight) var(--rly-type-meta-size) / var(--rly-type-meta-line-height)\n var(--rly-type-meta-font);\n }\n\n .thesis h1,\n .thesis p {\n margin: var(--rly-space-0);\n overflow-wrap: break-word;\n }\n\n /* Sized from the header's width, so a long word (\"idempotency\") fits a narrow header whole. */\n .thesis h1 {\n color: var(--rly-color-text-1);\n font: var(--rly-type-page-title-weight)\n clamp(var(--rly-type-card-title-size), 8cqi, var(--rly-type-page-title-size)) /\n var(--rly-type-page-title-line-height) var(--rly-type-page-title-font);\n letter-spacing: var(--rly-type-page-title-tracking);\n }\n\n .progress {\n align-content: center;\n border-inline-start: 1px solid var(--rly-color-border-1);\n display: grid;\n gap: var(--rly-space-12);\n min-inline-size: 15rem;\n padding: var(--rly-space-24);\n }\n\n .progress progress {\n accent-color: var(--rly-color-focus);\n block-size: var(--rly-space-6);\n inline-size: 100%;\n }\n\n .controls {\n align-items: center;\n border-block-start: 1px solid var(--rly-color-border-1);\n display: flex;\n flex-wrap: wrap;\n gap: var(--rly-space-8);\n grid-column: 1 / -1;\n padding: var(--rly-space-12) var(--rly-space-16);\n }\n\n .group {\n display: inline-flex;\n }\n\n .group button,\n .standalone {\n background: transparent;\n border: 1px solid var(--rly-color-border-2);\n color: var(--rly-color-text-2);\n cursor: pointer;\n font: var(--rly-type-label-weight) var(--rly-type-label-size) / var(--rly-type-label-line-height)\n var(--rly-type-label-font);\n min-block-size: 44px;\n padding: var(--rly-space-8) var(--rly-space-12);\n }\n\n .group button:first-child,\n .standalone {\n border-radius: var(--rly-radius-control) 0 0 var(--rly-radius-control);\n }\n\n .group button:last-child,\n .standalone {\n border-radius: 0 var(--rly-radius-control) var(--rly-radius-control) 0;\n }\n\n .group button + button {\n border-inline-start: 0;\n }\n\n .group button[aria-pressed=\"true\"],\n .standalone[aria-pressed=\"true\"] {\n background: var(--rly-color-surface-3);\n color: var(--rly-color-text-1);\n box-shadow: inset 0 -3px var(--rly-color-focus);\n }\n\n .group button:hover,\n .standalone:hover {\n background: var(--rly-color-surface-2);\n color: var(--rly-color-text-1);\n }\n\n .group button:focus-visible,\n .standalone:focus-visible {\n outline: 3px solid var(--rly-color-focus);\n outline-offset: var(--rly-space-2);\n position: relative;\n z-index: 1;\n }\n\n .standalone {\n border-radius: var(--rly-radius-control);\n }\n\n @container (max-width: 38rem) {\n .summary {\n grid-template-columns: minmax(var(--rly-space-0), 1fr);\n }\n\n .progress {\n border-block-start: 1px solid var(--rly-color-border-1);\n border-inline-start: 0;\n min-inline-size: var(--rly-space-0);\n padding-block-start: var(--rly-space-16);\n }\n\n .controls {\n align-items: stretch;\n display: grid;\n }\n\n .group {\n display: grid;\n grid-template-columns: repeat(2, minmax(var(--rly-space-0), 1fr));\n }\n\n .group button,\n .group button:first-child,\n .group button:last-child,\n .standalone {\n border: 1px solid var(--rly-color-border-2);\n border-radius: var(--rly-radius-control);\n }\n\n .thesis,\n .progress {\n padding-inline: var(--rly-space-16);\n }\n }\n}\n","@layer rly.components {\n .root {\n background: var(--rly-color-surface-1);\n border: 1px solid var(--rly-color-border-1);\n border-radius: var(--rly-radius-group);\n color: var(--rly-color-text-1);\n container-type: inline-size;\n min-inline-size: var(--rly-space-0);\n overflow: hidden;\n }\n\n .header {\n border-block-end: 1px solid var(--rly-color-border-1);\n min-inline-size: var(--rly-space-0);\n }\n\n .header > *,\n .inventory > *,\n .viewer > *,\n .findingItem > * {\n border: 0;\n border-radius: var(--rly-space-0);\n }\n\n .body {\n display: grid;\n grid-template-columns: minmax(14rem, 0.72fr) minmax(22rem, 2.1fr) minmax(17rem, 0.9fr);\n min-inline-size: var(--rly-space-0);\n }\n\n .inventory,\n .review,\n .viewer,\n .findings {\n min-inline-size: var(--rly-space-0);\n }\n\n .inventory,\n .review {\n border-inline-end: 1px solid var(--rly-color-border-1);\n }\n\n .review {\n display: grid;\n grid-template-rows: auto auto minmax(0, 1fr);\n }\n\n .scope,\n .findingsHeader {\n display: grid;\n gap: var(--rly-space-2);\n padding: var(--rly-space-16) var(--rly-space-20);\n }\n\n .scope {\n grid-template-columns: minmax(var(--rly-space-0), 1fr) auto;\n }\n\n .scopeLabel,\n .scopeValue {\n grid-column: 1;\n }\n\n .scope span,\n .findingsHeader > span,\n .notice,\n .empty {\n color: var(--rly-color-text-2);\n font: var(--rly-type-meta-weight) var(--rly-type-meta-size) / var(--rly-type-meta-line-height)\n var(--rly-type-meta-font);\n }\n\n .scopeValue {\n font: var(--rly-type-label-weight) var(--rly-type-label-size) / var(--rly-type-label-line-height)\n var(--rly-type-label-font);\n overflow-wrap: break-word;\n }\n\n .showAll {\n align-self: center;\n background: var(--rly-color-surface-2);\n border: 1px solid var(--rly-color-border-2);\n border-radius: var(--rly-radius-control);\n color: var(--rly-color-text-1);\n cursor: pointer;\n font: var(--rly-type-label-weight) var(--rly-type-label-size) / var(--rly-type-label-line-height)\n var(--rly-type-label-font);\n grid-column: 2;\n grid-row: 1 / 3;\n padding: var(--rly-space-8) var(--rly-space-12);\n }\n\n .showAll:hover {\n background: var(--rly-color-surface-3);\n }\n\n .showAll:focus-visible {\n outline: var(--rly-space-2) solid var(--rly-color-focus);\n outline-offset: var(--rly-space-2);\n }\n\n .notice {\n background: var(--rly-color-surface-2);\n border-block-start: 1px solid var(--rly-color-border-1);\n padding: calc(var(--rly-space-8) + var(--rly-space-2)) var(--rly-space-20);\n }\n\n .viewer {\n border-block-start: 1px solid var(--rly-color-border-1);\n overflow-x: auto;\n }\n\n .findings {\n align-content: start;\n display: grid;\n }\n\n .findingsHeader {\n grid-template-columns: minmax(var(--rly-space-0), 1fr) auto;\n }\n\n .findingsHeader h2 {\n margin: var(--rly-space-0);\n }\n\n .findingsHeader h2 {\n font: var(--rly-type-card-title-weight) var(--rly-type-card-title-size) / var(--rly-type-card-title-line-height)\n var(--rly-type-card-title-font);\n letter-spacing: var(--rly-type-card-title-tracking);\n }\n\n .findingsHeader > span {\n align-self: center;\n }\n\n .findingList {\n border-block-start: 1px solid var(--rly-color-border-1);\n list-style: none;\n margin: var(--rly-space-0);\n max-block-size: 48rem;\n overflow-y: auto;\n padding: var(--rly-space-0);\n }\n\n .findingList:focus-visible {\n outline: 2px solid var(--rly-color-focus);\n outline-offset: -2px;\n }\n\n .findingItem + .findingItem {\n border-block-start: 1px solid var(--rly-color-border-1);\n }\n\n .empty {\n border-block-start: 1px solid var(--rly-color-border-1);\n margin: var(--rly-space-0);\n padding: var(--rly-space-24) var(--rly-space-20);\n }\n\n @container (max-width: 58rem) {\n .body {\n grid-template-columns: minmax(var(--rly-space-0), 1fr);\n }\n\n .inventory,\n .review {\n border-block-end: 1px solid var(--rly-color-border-1);\n border-inline-end: 0;\n }\n\n .findingList {\n max-block-size: none;\n }\n }\n\n @container (max-width: 24rem) {\n .scope,\n .findingsHeader {\n padding-inline: calc(var(--rly-space-12) + var(--rly-space-2));\n }\n\n .notice,\n .empty {\n padding-inline: calc(var(--rly-space-12) + var(--rly-space-2));\n }\n }\n\n @media (forced-colors: active) {\n .notice,\n .showAll {\n forced-color-adjust: auto;\n }\n }\n}\n","import { CircleAlert, FilePenLine, FilePlus2, FileSymlink, FileX2, LoaderCircle } from \"lucide-react\"\nimport {\n type ComponentPropsWithRef,\n type ReactElement,\n type ReactNode,\n useEffect,\n useId,\n useMemo,\n useState\n} from \"react\"\nimport { classNames, cssClass, requireText } from \"../internal/component.js\"\nimport styles from \"./DiffFileTree.module.css\"\n\nconst style = (name: string): string => cssClass(styles, name)\n\n/** The provider change recorded for one path in the complete diff inventory. */\nexport type RlyDiffFileChange = \"added\" | \"modified\" | \"deleted\" | \"renamed\"\n\n/** Content readiness is independent from the file change, so exceptional files never disappear. */\nexport type RlyDiffFileContent =\n | { readonly state: \"ready\" }\n | { readonly label: string; readonly state: \"loading\" }\n | {\n readonly reason: string\n readonly state: \"binary\" | \"generated\" | \"oversized\" | \"unavailable\" | \"error\"\n }\n\ninterface RlyDiffFileBase {\n readonly content: RlyDiffFileContent\n readonly id: string\n readonly path: string\n}\n\n/** One indexed path. Renames always preserve both the previous and current path. */\nexport type RlyDiffFile =\n | (RlyDiffFileBase & { readonly change: \"renamed\"; readonly previousPath: string })\n | (RlyDiffFileBase & {\n readonly change: \"added\" | \"modified\" | \"deleted\"\n readonly previousPath?: never\n })\n\ninterface RlyIndexedInventory {\n readonly files: ReadonlyArray<RlyDiffFile>\n readonly indexedCount: number\n readonly totalCount: number\n}\n\n/** Complete or in-progress inventory state. Error states retain every path indexed so far. */\nexport type RlyDiffInventory =\n | { readonly files: ReadonlyArray<RlyDiffFile>; readonly state: \"ready\" }\n | (RlyIndexedInventory & { readonly label: string; readonly state: \"loading\" })\n | (RlyIndexedInventory & {\n readonly description: string\n readonly state: \"error\"\n readonly title: string\n })\n\n/** Props for a complete, application-controlled changed-file inventory. */\nexport type DiffFileTreeProps = Omit<ComponentPropsWithRef<\"nav\">, \"aria-label\" | \"children\"> & {\n readonly data: RlyDiffInventory\n readonly heading: string\n readonly onSelectedFileChange: (fileId: string) => void\n readonly selectedFileId?: string\n}\n\nconst contentLabel = (content: RlyDiffFileContent): string => {\n if (content.state === \"ready\") return \"Ready\"\n if (content.state === \"loading\") return requireText(content.label, \"DiffFileTree loading label\")\n return `${content.state}: ${requireText(content.reason, `DiffFileTree ${content.state} reason`)}`\n}\n\nconst visibleGitPath = (path: string): string =>\n path\n .split(\"/\")\n .map((segment) => (segment !== segment.trim() || /[\\t\\n\\v\\f\\r]/u.test(segment) ? JSON.stringify(segment) : segment))\n .join(\"/\")\n\n/** A path that may wrap after each `/`, so the full path stays visible instead of being ellipsised. */\nconst wrappableGitPath = (path: string): ReactNode =>\n visibleGitPath(path)\n .split(\"/\")\n .flatMap((segment, index) => (index === 0 ? [segment] : [\"/\", <wbr key={index} />, segment]))\n\nconst requireGitPath = (path: string, label: string): string => {\n if (path.length === 0) throw new Error(`${label} must not be empty`)\n return path\n}\n\nconst changeIcons = {\n added: FilePlus2,\n deleted: FileX2,\n modified: FilePenLine,\n renamed: FileSymlink\n} satisfies Record<RlyDiffFileChange, typeof FilePlus2>\n\nconst validateInventory = (data: RlyDiffInventory): void => {\n const ids = new Set<string>()\n for (const file of data.files) {\n const id = requireText(file.id, \"DiffFileTree file id\")\n if (ids.has(id)) throw new Error(`DiffFileTree file ids must be unique: ${id}`)\n ids.add(id)\n const path = requireGitPath(file.path, `DiffFileTree path for ${id}`)\n if (file.change === \"renamed\") {\n const previousPath = requireGitPath(file.previousPath, `DiffFileTree previousPath for ${id}`)\n if (previousPath === path) throw new Error(`DiffFileTree renamed paths must differ: ${id}`)\n }\n contentLabel(file.content)\n }\n\n if (data.state === \"loading\" || data.state === \"error\") {\n if (!Number.isInteger(data.indexedCount) || !Number.isInteger(data.totalCount)) {\n throw new Error(\"DiffFileTree counts must be integers\")\n }\n if (data.indexedCount !== data.files.length || data.totalCount < data.indexedCount) {\n throw new Error(\"DiffFileTree indexedCount must match visible files and cannot exceed totalCount\")\n }\n if (data.state === \"loading\") requireText(data.label, \"DiffFileTree loading label\")\n if (data.state === \"error\") {\n requireText(data.title, \"DiffFileTree error title\")\n requireText(data.description, \"DiffFileTree error description\")\n }\n }\n}\n\ninterface TreeFile {\n readonly file: RlyDiffFile\n readonly segments: ReadonlyArray<string>\n}\n\ntype FileTreeNode =\n | {\n readonly children: ReadonlyArray<FileTreeNode>\n readonly fileCount: number\n readonly kind: \"directory\"\n readonly name: string\n readonly path: string\n }\n | {\n readonly file: RlyDiffFile\n readonly kind: \"file\"\n readonly name: string\n }\n\nconst compactDirectory = (node: Extract<FileTreeNode, { readonly kind: \"directory\" }>): FileTreeNode => {\n if (node.children.length !== 1 || node.children[0]?.kind !== \"directory\") return node\n const child = node.children[0]\n return compactDirectory({\n ...child,\n name: `${node.name}/${child.name}`\n })\n}\n\nconst buildFileTree = (files: ReadonlyArray<TreeFile>, depth = 0): ReadonlyArray<FileTreeNode> => {\n const leaves: Array<FileTreeNode> = []\n const directories = new Map<string, Array<TreeFile>>()\n for (const treeFile of files) {\n const segment = treeFile.segments[depth]\n if (segment === undefined) continue\n if (depth === treeFile.segments.length - 1) {\n leaves.push({ file: treeFile.file, kind: \"file\", name: segment })\n continue\n }\n const grouped = directories.get(segment) ?? []\n grouped.push(treeFile)\n directories.set(segment, grouped)\n }\n const branches = Array.from(directories, ([name, grouped]) =>\n compactDirectory({\n children: buildFileTree(grouped, depth + 1),\n fileCount: grouped.length,\n kind: \"directory\",\n name,\n path: grouped[0]!.segments.slice(0, depth + 1).join(\"/\")\n })\n )\n return [...branches, ...leaves]\n}\n\nconst directoryAncestors = (path: string): ReadonlySet<string> => {\n const segments = path.split(\"/\")\n return new Set(segments.slice(0, -1).map((_, index) => segments.slice(0, index + 1).join(\"/\")))\n}\n\n/** Render every indexed path as a lightweight row without instantiating file content renderers. */\nexport const DiffFileTree = ({\n className,\n data,\n heading,\n onSelectedFileChange,\n selectedFileId,\n ...props\n}: DiffFileTreeProps): ReactElement => {\n const visibleHeading = requireText(heading, \"DiffFileTree heading\")\n validateInventory(data)\n if (selectedFileId !== undefined && !data.files.some((file) => file.id === selectedFileId)) {\n throw new Error(`DiffFileTree selectedFileId is not in the visible inventory: ${selectedFileId}`)\n }\n const headingId = `rly-diff-file-tree-${useId()}`\n const indexedCount = data.state === \"ready\" ? data.files.length : data.indexedCount\n const totalCount = data.state === \"ready\" ? data.files.length : data.totalCount\n const tree = useMemo(\n () =>\n buildFileTree(\n data.files.map((file) => ({\n file,\n segments: file.path.split(\"/\")\n }))\n ),\n [data.files]\n )\n const [collapsedDirectories, setCollapsedDirectories] = useState<ReadonlySet<string>>(() => new Set())\n const selectedPath = data.files.find(({ id }) => id === selectedFileId)?.path\n\n useEffect(() => {\n if (selectedPath === undefined) return\n const ancestors = directoryAncestors(selectedPath)\n setCollapsedDirectories((current) => {\n if (![...current].some((path) => ancestors.has(path))) return current\n return new Set([...current].filter((path) => !ancestors.has(path)))\n })\n }, [selectedPath])\n\n const renderNodes = (nodes: ReadonlyArray<FileTreeNode>): ReadonlyArray<ReactElement> =>\n nodes.map((node) => {\n if (node.kind === \"file\") {\n const isSelected = selectedFileId === node.file.id\n const ChangeIcon = changeIcons[node.file.change]\n const exceptionalContent = node.file.content.state === \"ready\" ? null : contentLabel(node.file.content)\n return (\n <li data-rly-diff-file-id={node.file.id} key={node.file.id}>\n <button\n aria-current={isSelected ? \"true\" : undefined}\n aria-label={`${visibleGitPath(node.file.path)}, ${node.file.change}, ${contentLabel(node.file.content)}`}\n className={style(\"file\")}\n data-rly-diff-content-state={node.file.content.state}\n data-rly-diff-file-change={node.file.change}\n onClick={() => onSelectedFileChange(node.file.id)}\n type=\"button\"\n >\n <span className={style(\"pathBlock\")} style={{ paddingInlineStart: \"var(--rly-space-20)\" }}>\n {node.file.change === \"renamed\" ? (\n <span className={style(\"previousPath\")}>{wrappableGitPath(node.file.previousPath)}</span>\n ) : null}\n <code className={style(\"path\")}>{wrappableGitPath(node.name)}</code>\n </span>\n <span className={style(\"statusIcons\")}>\n <span aria-hidden=\"true\" className={style(\"statusIcon\")} title={node.file.change}>\n <ChangeIcon />\n </span>\n {exceptionalContent === null ? null : (\n <span aria-hidden=\"true\" className={style(\"statusIcon\")} title={exceptionalContent}>\n {node.file.content.state === \"loading\" ? (\n <LoaderCircle className={style(\"loadingIcon\")} />\n ) : (\n <CircleAlert />\n )}\n </span>\n )}\n </span>\n </button>\n </li>\n )\n }\n const expanded = !collapsedDirectories.has(node.path)\n return (\n <li className={style(\"directory\")} data-rly-diff-directory={node.path} key={`directory:${node.path}`}>\n <button\n aria-expanded={expanded}\n aria-label={`${visibleGitPath(node.name)}, directory, ${node.fileCount} changed ${\n node.fileCount === 1 ? \"file\" : \"files\"\n }`}\n className={style(\"directoryButton\")}\n onClick={() =>\n setCollapsedDirectories((current) => {\n const next = new Set(current)\n if (expanded) next.add(node.path)\n else next.delete(node.path)\n return next\n })\n }\n type=\"button\"\n >\n <span aria-hidden=\"true\" className={style(\"chevron\")} />\n <code className={style(\"directoryName\")}>{wrappableGitPath(node.name)}</code>\n <span className={style(\"directoryCount\")}>{node.fileCount}</span>\n </button>\n {expanded ? (\n <ol className={style(\"group\")} style={{ marginInlineStart: \"var(--rly-space-16)\" }}>\n {renderNodes(node.children)}\n </ol>\n ) : null}\n </li>\n )\n })\n\n return (\n <nav\n {...props}\n aria-busy={data.state === \"loading\" ? \"true\" : undefined}\n aria-labelledby={headingId}\n className={classNames(style(\"root\"), className)}\n data-rly-diff-inventory-state={data.state}\n >\n <header className={style(\"header\")}>\n {/* The heading and a plain count in words; no eyebrow above it, no display-size figure. */}\n <h2 id={headingId}>{visibleHeading}</h2>\n <span className={style(\"count\")}>\n {indexedCount === totalCount ? `${totalCount} files` : `${indexedCount} of ${totalCount} files indexed`}\n </span>\n </header>\n\n {data.state === \"loading\" ? (\n <p className={style(\"notice\")} role=\"status\">\n {data.label}\n </p>\n ) : null}\n {data.state === \"error\" ? (\n <section className={style(\"error\")} role=\"alert\">\n <strong>{data.title}</strong>\n <span>{data.description}</span>\n </section>\n ) : null}\n\n {data.files.length === 0 ? (\n <p className={style(\"empty\")}>No changed files.</p>\n ) : (\n <ol className={style(\"list\")}>{renderNodes(tree)}</ol>\n )}\n </nav>\n )\n}\n","import { type ComponentPropsWithRef, type ReactElement, useId } from \"react\"\nimport { classNames, cssClass, requireText } from \"../internal/component.js\"\nimport styles from \"./DiffHeader.module.css\"\n\nconst style = (name: string): string => cssClass(styles, name)\n\n/** Controlled diff arrangement. */\nexport type RlyDiffLayout = \"split\" | \"stacked\"\n\n/** Controlled semantic finding filter. */\nexport type RlyDiffFindingFilter = \"all\" | \"human\" | \"agent\" | \"unresolved\"\n\n/** Props for the complete diff inventory thesis and its application-controlled view preferences. */\nexport type DiffHeaderProps = Omit<ComponentPropsWithRef<\"header\">, \"children\"> & {\n readonly findingFilter: RlyDiffFindingFilter\n readonly heading: string\n readonly indexedCount: number\n readonly isWrapped: boolean\n readonly layout: RlyDiffLayout\n readonly onFindingFilterChange: (filter: RlyDiffFindingFilter) => void\n readonly onLayoutChange: (layout: RlyDiffLayout) => void\n readonly onWrapChange: (isWrapped: boolean) => void\n readonly selectedFileLabel?: string\n readonly totalCount: number\n}\n\nconst findingFilters = [\"all\", \"human\", \"agent\", \"unresolved\"] satisfies ReadonlyArray<RlyDiffFindingFilter>\nconst layouts = [\"split\", \"stacked\"] satisfies ReadonlyArray<RlyDiffLayout>\n\nconst titleCase = (value: string): string => `${value.slice(0, 1).toUpperCase()}${value.slice(1)}`\n\nconst validateCounts = (indexedCount: number, totalCount: number): void => {\n if (!Number.isInteger(indexedCount) || !Number.isInteger(totalCount)) {\n throw new Error(\"DiffHeader counts must be integers\")\n }\n if (indexedCount < 0 || totalCount < 0 || indexedCount > totalCount) {\n throw new Error(\"DiffHeader indexedCount must be between zero and totalCount\")\n }\n}\n\n/** Render indexed progress and controlled preferences without fetching or rendering provider content. */\nexport const DiffHeader = ({\n className,\n findingFilter,\n heading,\n indexedCount,\n isWrapped,\n layout,\n onFindingFilterChange,\n onLayoutChange,\n onWrapChange,\n selectedFileLabel,\n totalCount,\n ...props\n}: DiffHeaderProps): ReactElement => {\n const visibleHeading = requireText(heading, \"DiffHeader heading\")\n if (selectedFileLabel !== undefined) requireText(selectedFileLabel, \"DiffHeader selectedFileLabel\")\n validateCounts(indexedCount, totalCount)\n const progressId = `rly-diff-header-progress-${useId()}`\n\n return (\n <header {...props} className={classNames(style(\"root\"), className)} data-rly-diff-layout={layout}>\n {/* The container's own child, so the narrow layout below can stack thesis and progress. */}\n <div className={style(\"summary\")}>\n <section className={style(\"thesis\")}>\n <h1>{visibleHeading}</h1>\n <p>{selectedFileLabel === undefined ? \"All changed files\" : selectedFileLabel}</p>\n </section>\n\n <section aria-labelledby={progressId} className={style(\"progress\")}>\n {/* One line of words in the flow, never a display figure that can run over the title. */}\n <span className={style(\"progressCopy\")} id={progressId}>\n {totalCount === 0\n ? \"No files to index\"\n : indexedCount === totalCount\n ? `All ${totalCount} files indexed`\n : `${indexedCount} of ${totalCount} files indexed`}\n </span>\n <progress max={Math.max(totalCount, 1)} value={indexedCount} />\n </section>\n </div>\n\n <div className={style(\"controls\")}>\n <div aria-label=\"Diff layout\" className={style(\"group\")} role=\"group\">\n {layouts.map((option) => (\n <button aria-pressed={layout === option} key={option} onClick={() => onLayoutChange(option)} type=\"button\">\n {titleCase(option)}\n </button>\n ))}\n </div>\n <button\n aria-pressed={isWrapped}\n className={style(\"standalone\")}\n onClick={() => onWrapChange(!isWrapped)}\n type=\"button\"\n >\n Wrap lines\n </button>\n <div aria-label=\"Finding filter\" className={style(\"group\")} role=\"group\">\n {findingFilters.map((filter) => (\n <button\n aria-pressed={findingFilter === filter}\n key={filter}\n onClick={() => onFindingFilterChange(filter)}\n type=\"button\"\n >\n {titleCase(filter)}\n </button>\n ))}\n </div>\n </div>\n </header>\n )\n}\n","import type { ComponentPropsWithRef, ReactElement, ReactNode } from \"react\"\nimport { classNames, cssClass, requireText } from \"../internal/component.js\"\nimport styles from \"./DiffWorkbench.module.css\"\n\nconst style = (name: string): string => cssClass(styles, name)\n\n/** The application-controlled file scope shown by the workbench. */\nexport type RlyDiffWorkbenchScope =\n | { readonly label: string; readonly mode: \"all-files\" }\n | { readonly fileId: string; readonly label: string; readonly mode: \"selected-file\" }\n\n/** One stable semantic finding slot, independent from virtualized line annotations. */\nexport interface RlyDiffWorkbenchFinding {\n readonly content: ReactNode\n readonly id: string\n}\n\n/** Presentation-only slots for a complete diff review surface. */\nexport type DiffWorkbenchProps = Omit<ComponentPropsWithRef<\"section\">, \"aria-label\" | \"children\"> & {\n readonly emptyFindings?: ReactNode\n readonly findings: ReadonlyArray<RlyDiffWorkbenchFinding>\n readonly findingsLabel?: string\n readonly header: ReactNode\n readonly inventory: ReactNode\n readonly inventoryLabel?: string\n readonly label: string\n readonly onShowAllFiles?: () => void\n readonly scope: RlyDiffWorkbenchScope\n readonly statusNotice?: ReactNode\n readonly viewer: ReactNode\n readonly viewerLabel?: string\n}\n\nconst validateFindings = (findings: ReadonlyArray<RlyDiffWorkbenchFinding>): void => {\n const ids = new Set<string>()\n for (const finding of findings) {\n const id = requireText(finding.id, \"DiffWorkbench finding id\")\n if (ids.has(id)) throw new Error(`DiffWorkbench finding ids must be unique: ${id}`)\n ids.add(id)\n }\n}\n\n/** Compose complete inventory, renderer, and semantic evidence without owning application state. */\nexport const DiffWorkbench = ({\n className,\n emptyFindings = \"No findings match this view.\",\n findings,\n findingsLabel = \"Semantic findings\",\n header,\n inventory,\n inventoryLabel = \"Changed files\",\n label,\n onShowAllFiles,\n scope,\n statusNotice,\n viewer,\n viewerLabel = \"Code changes\",\n ...props\n}: DiffWorkbenchProps): ReactElement => {\n const visibleLabel = requireText(label, \"DiffWorkbench label\")\n const visibleScopeLabel = requireText(scope.label, \"DiffWorkbench scope label\")\n const visibleInventoryLabel = requireText(inventoryLabel, \"DiffWorkbench inventoryLabel\")\n const visibleViewerLabel = requireText(viewerLabel, \"DiffWorkbench viewerLabel\")\n const visibleFindingsLabel = requireText(findingsLabel, \"DiffWorkbench findingsLabel\")\n if (scope.mode === \"selected-file\") {\n requireText(scope.fileId, \"DiffWorkbench selected file id\")\n if (onShowAllFiles === undefined) {\n throw new Error(\"DiffWorkbench selected-file scope requires onShowAllFiles\")\n }\n }\n validateFindings(findings)\n\n return (\n <section\n {...props}\n aria-label={visibleLabel}\n className={classNames(style(\"root\"), className)}\n data-rly-diff-scope={scope.mode}\n {...(scope.mode === \"selected-file\" ? { \"data-rly-diff-selected-file\": scope.fileId } : {})}\n >\n <div className={style(\"header\")} data-rly-diff-workbench-slot=\"header\">\n {header}\n </div>\n\n <div className={style(\"body\")}>\n <section\n aria-label={visibleInventoryLabel}\n className={style(\"inventory\")}\n data-rly-diff-workbench-slot=\"inventory\"\n >\n {inventory}\n </section>\n\n <div className={style(\"review\")}>\n <header className={style(\"scope\")}>\n <span className={style(\"scopeLabel\")}>{scope.mode === \"all-files\" ? \"All files\" : \"Selected file\"}</span>\n <strong className={style(\"scopeValue\")}>{visibleScopeLabel}</strong>\n {scope.mode === \"selected-file\" ? (\n <button className={style(\"showAll\")} onClick={onShowAllFiles} type=\"button\">\n Show all files\n </button>\n ) : null}\n </header>\n {statusNotice === undefined ? null : (\n <div aria-live=\"polite\" className={style(\"notice\")} data-rly-diff-workbench-slot=\"status\" role=\"status\">\n {statusNotice}\n </div>\n )}\n <section aria-label={visibleViewerLabel} className={style(\"viewer\")} data-rly-diff-workbench-slot=\"viewer\">\n {viewer}\n </section>\n </div>\n\n <aside aria-label={visibleFindingsLabel} className={style(\"findings\")} data-rly-diff-workbench-slot=\"findings\">\n <header className={style(\"findingsHeader\")}>\n {/* The heading and its count in words: no eyebrow, no display figure. */}\n <h2>{visibleFindingsLabel}</h2>\n <span>{findings.length === 1 ? \"1 finding\" : `${findings.length} findings`}</span>\n </header>\n {findings.length === 0 ? (\n <div className={style(\"empty\")}>{emptyFindings}</div>\n ) : (\n <ol aria-label={`${visibleFindingsLabel} list`} className={style(\"findingList\")} tabIndex={0}>\n {findings.map((finding) => (\n <li className={style(\"findingItem\")} key={finding.id}>\n {finding.content}\n </li>\n ))}\n </ol>\n )}\n </aside>\n </div>\n </section>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"workbench-CHCnYW3G.js","names":["root","header","notice","empty","group","root","style","styles","style","styles","styles","requireText","cssClass","classNames","DiffFileTree_module_default","DiffHeader_module_default","DiffWorkbench_module_default","style$2","name","contentLabel","content","visibleGitPath","path","segment","wrappableGitPath","index","requireGitPath","label","changeIcons","FilePlus2","FileX2","FilePenLine","FileSymlink","validateInventory","ids","file","data","id","compactDirectory","node","child","buildFileTree","leaves","directories","treeFile","files","depth","grouped","directoryAncestors","segments","DiffFileTree","props","visibleHeading","heading","selectedFileId","headingId","useId","indexedCount","totalCount","tree","useMemo","collapsedDirectories","setCollapsedDirectories","useState","selectedPath","ancestors","current","renderNodes","nodes","isSelected","ChangeIcon","exceptionalContent","onSelectedFileChange","LoaderCircle","CircleAlert","expanded","next","className","style$1","findingFilters","layouts","titleCase","value","validateCounts","DiffHeader","selectedFileLabel","progressId","layout","option","onLayoutChange","isWrapped","onWrapChange","findingFilter","filter","onFindingFilterChange","style","validateFindings","finding","findings","DiffWorkbench","visibleLabel","visibleScopeLabel","scope","visibleInventoryLabel","inventoryLabel","visibleViewerLabel","viewerLabel","visibleFindingsLabel","findingsLabel","onShowAllFiles","header","inventory","statusNotice","viewer","emptyFindings"],"sources":["../src/diff/DiffFileTree.module.css","../src/diff/DiffHeader.module.css","../src/diff/DiffWorkbench.module.css","../src/diff/DiffFileTree.tsx","../src/diff/DiffHeader.tsx","../src/diff/DiffWorkbench.tsx"],"sourcesContent":["@layer rly.components {\n .root {\n background: var(--rly-color-surface-1);\n border: 1px solid var(--rly-color-border-1);\n border-radius: var(--rly-radius-group);\n container-type: inline-size;\n display: grid;\n /* One bounded track: an implicit auto track can't shrink below its content, so it overflowed at 320. */\n grid-template-columns: minmax(var(--rly-space-0), 1fr);\n min-inline-size: var(--rly-space-0);\n overflow: hidden;\n }\n\n /* Heading and count share a row while they fit; the count wraps below in a narrow tree. */\n .header {\n align-items: baseline;\n display: flex;\n flex-wrap: wrap;\n gap: var(--rly-space-4) var(--rly-space-16);\n justify-content: space-between;\n padding: var(--rly-space-20);\n }\n\n .header > span {\n display: grid;\n gap: var(--rly-space-2);\n min-inline-size: var(--rly-space-0);\n }\n\n .header h2 {\n color: var(--rly-color-text-1);\n font: var(--rly-type-card-title-weight) var(--rly-type-card-title-size) / var(--rly-type-card-title-line-height)\n var(--rly-type-card-title-font);\n letter-spacing: var(--rly-type-card-title-tracking);\n margin: var(--rly-space-0);\n overflow-wrap: break-word;\n }\n\n .notice,\n .empty,\n .error,\n .previousPath {\n color: var(--rly-color-text-2);\n font: var(--rly-type-meta-weight) var(--rly-type-meta-size) / var(--rly-type-meta-line-height)\n var(--rly-type-meta-font);\n }\n\n .count {\n color: var(--rly-color-text-2);\n font: var(--rly-type-meta-weight) var(--rly-type-meta-size) / var(--rly-type-meta-line-height)\n var(--rly-type-meta-font);\n white-space: nowrap;\n }\n\n .notice,\n .empty,\n .error {\n border-block-start: 1px solid var(--rly-color-border-1);\n margin: var(--rly-space-0);\n padding: var(--rly-space-12) var(--rly-space-20);\n }\n\n .error {\n background: var(--rly-color-held-tint);\n display: grid;\n gap: var(--rly-space-2);\n }\n\n .error strong {\n color: var(--rly-color-text-1);\n }\n\n .list {\n border-block-start: 1px solid var(--rly-color-border-1);\n list-style: none;\n margin: var(--rly-space-0);\n max-block-size: 34rem;\n overflow: auto;\n padding: var(--rly-space-0);\n scrollbar-gutter: stable;\n }\n\n .list li:not(.directory) {\n contain: content;\n contain-intrinsic-block-size: 40px;\n }\n\n .group {\n list-style: none;\n margin: var(--rly-space-0);\n padding: var(--rly-space-0);\n }\n\n .group > li {\n position: relative;\n }\n\n .group > li::before {\n block-size: 20px;\n border-block-end: 1px solid var(--rly-color-border-2);\n border-inline-start: 1px solid var(--rly-color-border-2);\n content: \"\";\n inline-size: var(--rly-space-12);\n inset-block-start: var(--rly-space-0);\n inset-inline-start: var(--rly-space-0);\n pointer-events: none;\n position: absolute;\n z-index: 1;\n }\n\n .group > li:not(:last-child)::after {\n border-inline-start: 1px solid var(--rly-color-border-2);\n content: \"\";\n inset-block: 20px var(--rly-space-0);\n inset-inline-start: var(--rly-space-0);\n pointer-events: none;\n position: absolute;\n z-index: 1;\n }\n\n .directoryButton {\n align-items: center;\n background: transparent;\n border: 0;\n border-block-end: 1px solid var(--rly-color-border-1);\n color: var(--rly-color-text-1);\n cursor: pointer;\n display: grid;\n gap: var(--rly-space-8);\n grid-template-columns: var(--rly-space-12) minmax(var(--rly-space-0), 1fr) auto;\n inline-size: 100%;\n min-block-size: var(--rly-space-32);\n padding: var(--rly-space-8) var(--rly-space-12);\n text-align: start;\n }\n\n .directoryButton:hover {\n background: var(--rly-color-surface-2);\n }\n\n .directoryButton:focus-visible {\n outline: var(--rly-focus-ring-width) solid var(--rly-color-focus);\n outline-offset: calc(var(--rly-focus-ring-width) * -1);\n }\n\n .chevron {\n block-size: var(--rly-space-8);\n border-block-end: 1.5px solid currentcolor; /* stripe-ok: drawn chevron, two edges of a rotated square */\n border-inline-end: 1.5px solid currentcolor; /* stripe-ok: drawn chevron, mirrors in right-to-left text */\n inline-size: var(--rly-space-8);\n justify-self: center;\n /* --rly-diff-tree-turn is 1 in left-to-right text and -1 in right-to-left; see below. */\n transform: rotate(calc(45deg * var(--rly-diff-tree-turn, 1)))\n translate(calc(-1px * var(--rly-diff-tree-turn, 1)), -1px);\n transition: transform var(--rly-motion-fast-duration) var(--rly-motion-fast-easing);\n }\n\n .directoryButton[aria-expanded=\"false\"] .chevron {\n transform: rotate(calc(-45deg * var(--rly-diff-tree-turn, 1)));\n }\n\n /*\n * In right-to-left text the edges sit on the left, so the turns mirror: down when open, left when\n * shut. Each dir attribute sets the sign and the nearest one is inherited, so an LTR tree inside an\n * RTL page turns the LTR way. (The build lowers :dir() to a :lang() list, so it cannot be used.)\n */\n [dir=\"rtl\"] {\n --rly-diff-tree-turn: -1;\n }\n\n [dir=\"ltr\"] {\n --rly-diff-tree-turn: 1;\n }\n\n .directoryName {\n font: var(--rly-type-code-weight) var(--rly-type-code-size) / var(--rly-type-code-line-height)\n var(--rly-type-code-font);\n min-inline-size: var(--rly-space-0);\n overflow-wrap: break-word;\n }\n\n .directoryCount {\n color: var(--rly-color-text-3);\n font: var(--rly-type-meta-weight) var(--rly-type-meta-size) / var(--rly-type-meta-line-height)\n var(--rly-type-meta-font);\n font-variant-numeric: tabular-nums;\n }\n\n .file {\n align-items: center;\n background: transparent;\n border: 0;\n border-block-end: 1px solid var(--rly-color-border-1);\n color: inherit;\n cursor: pointer;\n display: grid;\n gap: var(--rly-space-8);\n grid-template-columns: minmax(var(--rly-space-0), 1fr) auto;\n inline-size: 100%;\n min-block-size: 40px;\n padding: var(--rly-space-6) var(--rly-space-12);\n text-align: start;\n }\n\n .file:hover {\n background: var(--rly-color-surface-2);\n }\n\n .file[aria-current=\"true\"] {\n background: var(--rly-color-surface-3);\n box-shadow: inset 0 0 0 1px var(--rly-color-border-2);\n }\n\n .file:focus-visible {\n outline: var(--rly-focus-ring-width) solid var(--rly-color-focus);\n outline-offset: calc(var(--rly-focus-ring-width) * -1);\n }\n\n .pathBlock {\n display: grid;\n min-inline-size: var(--rly-space-0);\n }\n\n /* A path is the file's identity: it wraps after a slash (or, for one long name, inside it), never ellipsised. */\n .path,\n .previousPath {\n min-inline-size: var(--rly-space-0);\n overflow-wrap: break-word;\n }\n\n .path {\n color: var(--rly-color-text-1);\n font: var(--rly-type-code-weight) var(--rly-type-code-size) / var(--rly-type-code-line-height)\n var(--rly-type-code-font);\n }\n\n .previousPath {\n text-decoration: line-through;\n }\n\n .statusIcons {\n align-items: center;\n color: var(--rly-color-text-2);\n display: inline-flex;\n gap: var(--rly-space-4);\n }\n\n .statusIcon,\n .statusIcon svg {\n block-size: var(--rly-space-16);\n inline-size: var(--rly-space-16);\n }\n .statusIcon svg {\n display: block;\n }\n\n .loadingIcon {\n animation: rly-diff-file-tree-spin 800ms linear infinite;\n }\n\n @keyframes rly-diff-file-tree-spin {\n to {\n transform: rotate(360deg);\n }\n }\n\n @container (max-width: 24rem) {\n .header {\n align-items: start;\n }\n\n .file {\n grid-template-columns: minmax(var(--rly-space-0), 1fr) auto;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .chevron,\n .loadingIcon {\n animation: none;\n transition: none;\n }\n }\n}\n","@layer rly.components {\n .root {\n background: var(--rly-color-surface-1);\n border: 1px solid var(--rly-color-border-1);\n border-radius: var(--rly-radius-group);\n container-type: inline-size;\n display: grid;\n min-inline-size: var(--rly-space-0);\n overflow: hidden;\n }\n\n /* Thesis and progress side by side; a container query below stacks them. A container cannot\n query itself, so the layout lives on this child, not on .root. */\n .summary {\n display: grid;\n grid-template-columns: minmax(var(--rly-space-0), 1fr) auto;\n min-inline-size: var(--rly-space-0);\n }\n\n .thesis {\n display: grid;\n grid-template-columns: minmax(var(--rly-space-0), 1fr);\n min-inline-size: var(--rly-space-0);\n gap: var(--rly-space-4);\n padding: var(--rly-space-24);\n }\n\n .thesis p,\n .progressCopy {\n color: var(--rly-color-text-2);\n font: var(--rly-type-meta-weight) var(--rly-type-meta-size) / var(--rly-type-meta-line-height)\n var(--rly-type-meta-font);\n }\n\n .thesis h1,\n .thesis p {\n margin: var(--rly-space-0);\n overflow-wrap: break-word;\n }\n\n /* Sized from the header's width, so a long word (\"idempotency\") fits a narrow header whole. */\n .thesis h1 {\n color: var(--rly-color-text-1);\n font: var(--rly-type-page-title-weight)\n clamp(var(--rly-type-card-title-size), 8cqi, var(--rly-type-page-title-size)) /\n var(--rly-type-page-title-line-height) var(--rly-type-page-title-font);\n letter-spacing: var(--rly-type-page-title-tracking);\n }\n\n .progress {\n align-content: center;\n border-inline-start: 1px solid var(--rly-color-border-1);\n display: grid;\n gap: var(--rly-space-12);\n min-inline-size: 15rem;\n padding: var(--rly-space-24);\n }\n\n .progress progress {\n accent-color: var(--rly-color-focus);\n block-size: var(--rly-space-6);\n inline-size: 100%;\n }\n\n .controls {\n align-items: center;\n border-block-start: 1px solid var(--rly-color-border-1);\n display: flex;\n flex-wrap: wrap;\n gap: var(--rly-space-8);\n grid-column: 1 / -1;\n padding: var(--rly-space-12) var(--rly-space-16);\n }\n\n .group {\n display: inline-flex;\n }\n\n .group button,\n .standalone {\n background: transparent;\n border: 1px solid var(--rly-color-border-2);\n color: var(--rly-color-text-2);\n cursor: pointer;\n font: var(--rly-type-label-weight) var(--rly-type-label-size) / var(--rly-type-label-line-height)\n var(--rly-type-label-font);\n min-block-size: 44px;\n padding: var(--rly-space-8) var(--rly-space-12);\n }\n\n .group button:first-child,\n .standalone {\n border-radius: var(--rly-radius-control) 0 0 var(--rly-radius-control);\n }\n\n .group button:last-child,\n .standalone {\n border-radius: 0 var(--rly-radius-control) var(--rly-radius-control) 0;\n }\n\n .group button + button {\n border-inline-start: 0;\n }\n\n .group button[aria-pressed=\"true\"],\n .standalone[aria-pressed=\"true\"] {\n background: var(--rly-color-surface-3);\n color: var(--rly-color-text-1);\n /* Pressed is marked in text ink; the focus colour is reserved for the focus ring. */\n box-shadow: inset 0 -2px var(--rly-color-text-1);\n }\n\n .group button:hover,\n .standalone:hover {\n background: var(--rly-color-surface-2);\n color: var(--rly-color-text-1);\n }\n\n .group button:focus-visible,\n .standalone:focus-visible {\n outline: var(--rly-focus-ring-width) solid var(--rly-color-focus);\n outline-offset: var(--rly-focus-ring-offset);\n position: relative;\n z-index: 1;\n }\n\n .standalone {\n border-radius: var(--rly-radius-control);\n }\n\n @container (max-width: 38rem) {\n .summary {\n grid-template-columns: minmax(var(--rly-space-0), 1fr);\n }\n\n .progress {\n border-block-start: 1px solid var(--rly-color-border-1);\n border-inline-start: 0;\n min-inline-size: var(--rly-space-0);\n padding-block-start: var(--rly-space-16);\n }\n\n .controls {\n align-items: stretch;\n display: grid;\n }\n\n .group {\n display: grid;\n grid-template-columns: repeat(2, minmax(var(--rly-space-0), 1fr));\n }\n\n .group button,\n .group button:first-child,\n .group button:last-child,\n .standalone {\n border: 1px solid var(--rly-color-border-2);\n border-radius: var(--rly-radius-control);\n }\n\n .thesis,\n .progress {\n padding-inline: var(--rly-space-16);\n }\n }\n}\n","@layer rly.components {\n .root {\n background: var(--rly-color-surface-1);\n border: 1px solid var(--rly-color-border-1);\n border-radius: var(--rly-radius-group);\n color: var(--rly-color-text-1);\n container-type: inline-size;\n min-inline-size: var(--rly-space-0);\n overflow: hidden;\n }\n\n .header {\n border-block-end: 1px solid var(--rly-color-border-1);\n min-inline-size: var(--rly-space-0);\n }\n\n .header > *,\n .inventory > *,\n .viewer > *,\n .findingItem > * {\n border: 0;\n border-radius: var(--rly-space-0);\n }\n\n .body {\n display: grid;\n grid-template-columns: minmax(14rem, 0.72fr) minmax(22rem, 2.1fr) minmax(17rem, 0.9fr);\n min-inline-size: var(--rly-space-0);\n }\n\n .inventory,\n .review,\n .viewer,\n .findings {\n min-inline-size: var(--rly-space-0);\n }\n\n .inventory,\n .review {\n border-inline-end: 1px solid var(--rly-color-border-1);\n }\n\n .review {\n display: grid;\n grid-template-rows: auto auto minmax(0, 1fr);\n }\n\n .scope,\n .findingsHeader {\n display: grid;\n gap: var(--rly-space-2);\n padding: var(--rly-space-16) var(--rly-space-20);\n }\n\n .scope {\n grid-template-columns: minmax(var(--rly-space-0), 1fr) auto;\n }\n\n .scopeLabel,\n .scopeValue {\n grid-column: 1;\n }\n\n .scope span,\n .findingsHeader > span,\n .notice,\n .empty {\n color: var(--rly-color-text-2);\n font: var(--rly-type-meta-weight) var(--rly-type-meta-size) / var(--rly-type-meta-line-height)\n var(--rly-type-meta-font);\n }\n\n .scopeValue {\n font: var(--rly-type-label-weight) var(--rly-type-label-size) / var(--rly-type-label-line-height)\n var(--rly-type-label-font);\n overflow-wrap: break-word;\n }\n\n .showAll {\n align-self: center;\n background: var(--rly-color-surface-2);\n border: 1px solid var(--rly-color-border-2);\n border-radius: var(--rly-radius-control);\n color: var(--rly-color-text-1);\n cursor: pointer;\n font: var(--rly-type-label-weight) var(--rly-type-label-size) / var(--rly-type-label-line-height)\n var(--rly-type-label-font);\n grid-column: 2;\n grid-row: 1 / 3;\n padding: var(--rly-space-8) var(--rly-space-12);\n }\n\n .showAll:hover {\n background: var(--rly-color-surface-3);\n }\n\n .showAll:focus-visible {\n outline: var(--rly-focus-ring-width) solid var(--rly-color-focus);\n outline-offset: var(--rly-focus-ring-offset);\n }\n\n .notice {\n background: var(--rly-color-surface-2);\n border-block-start: 1px solid var(--rly-color-border-1);\n padding: calc(var(--rly-space-8) + var(--rly-space-2)) var(--rly-space-20);\n }\n\n .viewer {\n border-block-start: 1px solid var(--rly-color-border-1);\n overflow-x: auto;\n }\n\n .findings {\n align-content: start;\n display: grid;\n }\n\n .findingsHeader {\n grid-template-columns: minmax(var(--rly-space-0), 1fr) auto;\n }\n\n .findingsHeader h2 {\n margin: var(--rly-space-0);\n }\n\n .findingsHeader h2 {\n font: var(--rly-type-card-title-weight) var(--rly-type-card-title-size) / var(--rly-type-card-title-line-height)\n var(--rly-type-card-title-font);\n letter-spacing: var(--rly-type-card-title-tracking);\n }\n\n .findingsHeader > span {\n align-self: center;\n }\n\n .findingList {\n border-block-start: 1px solid var(--rly-color-border-1);\n list-style: none;\n margin: var(--rly-space-0);\n max-block-size: 48rem;\n overflow-y: auto;\n padding: var(--rly-space-0);\n }\n\n .findingList:focus-visible {\n outline: var(--rly-focus-ring-width) solid var(--rly-color-focus);\n outline-offset: calc(var(--rly-focus-ring-width) * -1);\n }\n\n .findingItem + .findingItem {\n border-block-start: 1px solid var(--rly-color-border-1);\n }\n\n .empty {\n border-block-start: 1px solid var(--rly-color-border-1);\n margin: var(--rly-space-0);\n padding: var(--rly-space-24) var(--rly-space-20);\n }\n\n @container (max-width: 58rem) {\n .body {\n grid-template-columns: minmax(var(--rly-space-0), 1fr);\n }\n\n .inventory,\n .review {\n border-block-end: 1px solid var(--rly-color-border-1);\n border-inline-end: 0;\n }\n\n .findingList {\n max-block-size: none;\n }\n }\n\n @container (max-width: 24rem) {\n .scope,\n .findingsHeader {\n padding-inline: calc(var(--rly-space-12) + var(--rly-space-2));\n }\n\n .notice,\n .empty {\n padding-inline: calc(var(--rly-space-12) + var(--rly-space-2));\n }\n }\n\n @media (forced-colors: active) {\n .notice,\n .showAll {\n forced-color-adjust: auto;\n }\n }\n}\n","import { CircleAlert, FilePenLine, FilePlus2, FileSymlink, FileX2, LoaderCircle } from \"lucide-react\"\nimport {\n type ComponentPropsWithRef,\n type ReactElement,\n type ReactNode,\n useEffect,\n useId,\n useMemo,\n useState\n} from \"react\"\nimport { classNames, cssClass, requireText } from \"../internal/component.js\"\nimport styles from \"./DiffFileTree.module.css\"\n\nconst style = (name: string): string => cssClass(styles, name)\n\n/** The provider change recorded for one path in the complete diff inventory. */\nexport type RlyDiffFileChange = \"added\" | \"modified\" | \"deleted\" | \"renamed\"\n\n/** Content readiness is independent from the file change, so exceptional files never disappear. */\nexport type RlyDiffFileContent =\n | { readonly state: \"ready\" }\n | { readonly label: string; readonly state: \"loading\" }\n | {\n readonly reason: string\n readonly state: \"binary\" | \"generated\" | \"oversized\" | \"unavailable\" | \"error\"\n }\n\ninterface RlyDiffFileBase {\n readonly content: RlyDiffFileContent\n readonly id: string\n readonly path: string\n}\n\n/** One indexed path. Renames always preserve both the previous and current path. */\nexport type RlyDiffFile =\n | (RlyDiffFileBase & { readonly change: \"renamed\"; readonly previousPath: string })\n | (RlyDiffFileBase & {\n readonly change: \"added\" | \"modified\" | \"deleted\"\n readonly previousPath?: never\n })\n\ninterface RlyIndexedInventory {\n readonly files: ReadonlyArray<RlyDiffFile>\n readonly indexedCount: number\n readonly totalCount: number\n}\n\n/** Complete or in-progress inventory state. Error states retain every path indexed so far. */\nexport type RlyDiffInventory =\n | { readonly files: ReadonlyArray<RlyDiffFile>; readonly state: \"ready\" }\n | (RlyIndexedInventory & { readonly label: string; readonly state: \"loading\" })\n | (RlyIndexedInventory & {\n readonly description: string\n readonly state: \"error\"\n readonly title: string\n })\n\n/** Props for a complete, application-controlled changed-file inventory. */\nexport type DiffFileTreeProps = Omit<ComponentPropsWithRef<\"nav\">, \"aria-label\" | \"children\"> & {\n readonly data: RlyDiffInventory\n readonly heading: string\n readonly onSelectedFileChange: (fileId: string) => void\n readonly selectedFileId?: string\n}\n\nconst contentLabel = (content: RlyDiffFileContent): string => {\n if (content.state === \"ready\") return \"Ready\"\n if (content.state === \"loading\") return requireText(content.label, \"DiffFileTree loading label\")\n return `${content.state}: ${requireText(content.reason, `DiffFileTree ${content.state} reason`)}`\n}\n\nconst visibleGitPath = (path: string): string =>\n path\n .split(\"/\")\n .map((segment) => (segment !== segment.trim() || /[\\t\\n\\v\\f\\r]/u.test(segment) ? JSON.stringify(segment) : segment))\n .join(\"/\")\n\n/** A path that may wrap after each `/`, so the full path stays visible instead of being ellipsised. */\nconst wrappableGitPath = (path: string): ReactNode =>\n visibleGitPath(path)\n .split(\"/\")\n .flatMap((segment, index) => (index === 0 ? [segment] : [\"/\", <wbr key={index} />, segment]))\n\nconst requireGitPath = (path: string, label: string): string => {\n if (path.length === 0) throw new Error(`${label} must not be empty`)\n return path\n}\n\nconst changeIcons = {\n added: FilePlus2,\n deleted: FileX2,\n modified: FilePenLine,\n renamed: FileSymlink\n} satisfies Record<RlyDiffFileChange, typeof FilePlus2>\n\nconst validateInventory = (data: RlyDiffInventory): void => {\n const ids = new Set<string>()\n for (const file of data.files) {\n const id = requireText(file.id, \"DiffFileTree file id\")\n if (ids.has(id)) throw new Error(`DiffFileTree file ids must be unique: ${id}`)\n ids.add(id)\n const path = requireGitPath(file.path, `DiffFileTree path for ${id}`)\n if (file.change === \"renamed\") {\n const previousPath = requireGitPath(file.previousPath, `DiffFileTree previousPath for ${id}`)\n if (previousPath === path) throw new Error(`DiffFileTree renamed paths must differ: ${id}`)\n }\n contentLabel(file.content)\n }\n\n if (data.state === \"loading\" || data.state === \"error\") {\n if (!Number.isInteger(data.indexedCount) || !Number.isInteger(data.totalCount)) {\n throw new Error(\"DiffFileTree counts must be integers\")\n }\n if (data.indexedCount !== data.files.length || data.totalCount < data.indexedCount) {\n throw new Error(\"DiffFileTree indexedCount must match visible files and cannot exceed totalCount\")\n }\n if (data.state === \"loading\") requireText(data.label, \"DiffFileTree loading label\")\n if (data.state === \"error\") {\n requireText(data.title, \"DiffFileTree error title\")\n requireText(data.description, \"DiffFileTree error description\")\n }\n }\n}\n\ninterface TreeFile {\n readonly file: RlyDiffFile\n readonly segments: ReadonlyArray<string>\n}\n\ntype FileTreeNode =\n | {\n readonly children: ReadonlyArray<FileTreeNode>\n readonly fileCount: number\n readonly kind: \"directory\"\n readonly name: string\n readonly path: string\n }\n | {\n readonly file: RlyDiffFile\n readonly kind: \"file\"\n readonly name: string\n }\n\nconst compactDirectory = (node: Extract<FileTreeNode, { readonly kind: \"directory\" }>): FileTreeNode => {\n if (node.children.length !== 1 || node.children[0]?.kind !== \"directory\") return node\n const child = node.children[0]\n return compactDirectory({\n ...child,\n name: `${node.name}/${child.name}`\n })\n}\n\nconst buildFileTree = (files: ReadonlyArray<TreeFile>, depth = 0): ReadonlyArray<FileTreeNode> => {\n const leaves: Array<FileTreeNode> = []\n const directories = new Map<string, Array<TreeFile>>()\n for (const treeFile of files) {\n const segment = treeFile.segments[depth]\n if (segment === undefined) continue\n if (depth === treeFile.segments.length - 1) {\n leaves.push({ file: treeFile.file, kind: \"file\", name: segment })\n continue\n }\n const grouped = directories.get(segment) ?? []\n grouped.push(treeFile)\n directories.set(segment, grouped)\n }\n const branches = Array.from(directories, ([name, grouped]) =>\n compactDirectory({\n children: buildFileTree(grouped, depth + 1),\n fileCount: grouped.length,\n kind: \"directory\",\n name,\n path: grouped[0]!.segments.slice(0, depth + 1).join(\"/\")\n })\n )\n return [...branches, ...leaves]\n}\n\nconst directoryAncestors = (path: string): ReadonlySet<string> => {\n const segments = path.split(\"/\")\n return new Set(segments.slice(0, -1).map((_, index) => segments.slice(0, index + 1).join(\"/\")))\n}\n\n/** Render every indexed path as a lightweight row without instantiating file content renderers. */\nexport const DiffFileTree = ({\n className,\n data,\n heading,\n onSelectedFileChange,\n selectedFileId,\n ...props\n}: DiffFileTreeProps): ReactElement => {\n const visibleHeading = requireText(heading, \"DiffFileTree heading\")\n validateInventory(data)\n if (selectedFileId !== undefined && !data.files.some((file) => file.id === selectedFileId)) {\n throw new Error(`DiffFileTree selectedFileId is not in the visible inventory: ${selectedFileId}`)\n }\n const headingId = `rly-diff-file-tree-${useId()}`\n const indexedCount = data.state === \"ready\" ? data.files.length : data.indexedCount\n const totalCount = data.state === \"ready\" ? data.files.length : data.totalCount\n const tree = useMemo(\n () =>\n buildFileTree(\n data.files.map((file) => ({\n file,\n segments: file.path.split(\"/\")\n }))\n ),\n [data.files]\n )\n const [collapsedDirectories, setCollapsedDirectories] = useState<ReadonlySet<string>>(() => new Set())\n const selectedPath = data.files.find(({ id }) => id === selectedFileId)?.path\n\n useEffect(() => {\n if (selectedPath === undefined) return\n const ancestors = directoryAncestors(selectedPath)\n setCollapsedDirectories((current) => {\n if (![...current].some((path) => ancestors.has(path))) return current\n return new Set([...current].filter((path) => !ancestors.has(path)))\n })\n }, [selectedPath])\n\n const renderNodes = (nodes: ReadonlyArray<FileTreeNode>): ReadonlyArray<ReactElement> =>\n nodes.map((node) => {\n if (node.kind === \"file\") {\n const isSelected = selectedFileId === node.file.id\n const ChangeIcon = changeIcons[node.file.change]\n const exceptionalContent = node.file.content.state === \"ready\" ? null : contentLabel(node.file.content)\n return (\n <li data-rly-diff-file-id={node.file.id} key={node.file.id}>\n <button\n aria-current={isSelected ? \"true\" : undefined}\n aria-label={`${visibleGitPath(node.file.path)}, ${node.file.change}, ${contentLabel(node.file.content)}`}\n className={style(\"file\")}\n data-rly-diff-content-state={node.file.content.state}\n data-rly-diff-file-change={node.file.change}\n onClick={() => onSelectedFileChange(node.file.id)}\n type=\"button\"\n >\n <span className={style(\"pathBlock\")} style={{ paddingInlineStart: \"var(--rly-space-20)\" }}>\n {node.file.change === \"renamed\" ? (\n <span className={style(\"previousPath\")}>{wrappableGitPath(node.file.previousPath)}</span>\n ) : null}\n <code className={style(\"path\")}>{wrappableGitPath(node.name)}</code>\n </span>\n <span className={style(\"statusIcons\")}>\n <span aria-hidden=\"true\" className={style(\"statusIcon\")} title={node.file.change}>\n <ChangeIcon />\n </span>\n {exceptionalContent === null ? null : (\n <span aria-hidden=\"true\" className={style(\"statusIcon\")} title={exceptionalContent}>\n {node.file.content.state === \"loading\" ? (\n <LoaderCircle className={style(\"loadingIcon\")} />\n ) : (\n <CircleAlert />\n )}\n </span>\n )}\n </span>\n </button>\n </li>\n )\n }\n const expanded = !collapsedDirectories.has(node.path)\n return (\n <li className={style(\"directory\")} data-rly-diff-directory={node.path} key={`directory:${node.path}`}>\n <button\n aria-expanded={expanded}\n aria-label={`${visibleGitPath(node.name)}, directory, ${node.fileCount} changed ${\n node.fileCount === 1 ? \"file\" : \"files\"\n }`}\n className={style(\"directoryButton\")}\n onClick={() =>\n setCollapsedDirectories((current) => {\n const next = new Set(current)\n if (expanded) next.add(node.path)\n else next.delete(node.path)\n return next\n })\n }\n type=\"button\"\n >\n <span aria-hidden=\"true\" className={style(\"chevron\")} />\n <code className={style(\"directoryName\")}>{wrappableGitPath(node.name)}</code>\n <span className={style(\"directoryCount\")}>{node.fileCount}</span>\n </button>\n {expanded ? (\n <ol className={style(\"group\")} style={{ marginInlineStart: \"var(--rly-space-16)\" }}>\n {renderNodes(node.children)}\n </ol>\n ) : null}\n </li>\n )\n })\n\n return (\n <nav\n {...props}\n aria-busy={data.state === \"loading\" ? \"true\" : undefined}\n aria-labelledby={headingId}\n className={classNames(style(\"root\"), className)}\n data-rly-diff-inventory-state={data.state}\n >\n <header className={style(\"header\")}>\n {/* The heading and a plain count in words; no eyebrow above it, no display-size figure. */}\n <h2 id={headingId}>{visibleHeading}</h2>\n <span className={style(\"count\")}>\n {indexedCount === totalCount ? `${totalCount} files` : `${indexedCount} of ${totalCount} files indexed`}\n </span>\n </header>\n\n {data.state === \"loading\" ? (\n <p className={style(\"notice\")} role=\"status\">\n {data.label}\n </p>\n ) : null}\n {data.state === \"error\" ? (\n <section className={style(\"error\")} role=\"alert\">\n <strong>{data.title}</strong>\n <span>{data.description}</span>\n </section>\n ) : null}\n\n {data.files.length === 0 ? (\n <p className={style(\"empty\")}>No changed files.</p>\n ) : (\n <ol className={style(\"list\")}>{renderNodes(tree)}</ol>\n )}\n </nav>\n )\n}\n","import { type ComponentPropsWithRef, type ReactElement, useId } from \"react\"\nimport { classNames, cssClass, requireText } from \"../internal/component.js\"\nimport styles from \"./DiffHeader.module.css\"\n\nconst style = (name: string): string => cssClass(styles, name)\n\n/** Controlled diff arrangement. */\nexport type RlyDiffLayout = \"split\" | \"stacked\"\n\n/** Controlled semantic finding filter. */\nexport type RlyDiffFindingFilter = \"all\" | \"human\" | \"agent\" | \"unresolved\"\n\n/** Props for the complete diff inventory thesis and its application-controlled view preferences. */\nexport type DiffHeaderProps = Omit<ComponentPropsWithRef<\"header\">, \"children\"> & {\n readonly findingFilter: RlyDiffFindingFilter\n readonly heading: string\n readonly indexedCount: number\n readonly isWrapped: boolean\n readonly layout: RlyDiffLayout\n readonly onFindingFilterChange: (filter: RlyDiffFindingFilter) => void\n readonly onLayoutChange: (layout: RlyDiffLayout) => void\n readonly onWrapChange: (isWrapped: boolean) => void\n readonly selectedFileLabel?: string\n readonly totalCount: number\n}\n\nconst findingFilters = [\"all\", \"human\", \"agent\", \"unresolved\"] satisfies ReadonlyArray<RlyDiffFindingFilter>\nconst layouts = [\"split\", \"stacked\"] satisfies ReadonlyArray<RlyDiffLayout>\n\nconst titleCase = (value: string): string => `${value.slice(0, 1).toUpperCase()}${value.slice(1)}`\n\nconst validateCounts = (indexedCount: number, totalCount: number): void => {\n if (!Number.isInteger(indexedCount) || !Number.isInteger(totalCount)) {\n throw new Error(\"DiffHeader counts must be integers\")\n }\n if (indexedCount < 0 || totalCount < 0 || indexedCount > totalCount) {\n throw new Error(\"DiffHeader indexedCount must be between zero and totalCount\")\n }\n}\n\n/** Render indexed progress and controlled preferences without fetching or rendering provider content. */\nexport const DiffHeader = ({\n className,\n findingFilter,\n heading,\n indexedCount,\n isWrapped,\n layout,\n onFindingFilterChange,\n onLayoutChange,\n onWrapChange,\n selectedFileLabel,\n totalCount,\n ...props\n}: DiffHeaderProps): ReactElement => {\n const visibleHeading = requireText(heading, \"DiffHeader heading\")\n if (selectedFileLabel !== undefined) requireText(selectedFileLabel, \"DiffHeader selectedFileLabel\")\n validateCounts(indexedCount, totalCount)\n const progressId = `rly-diff-header-progress-${useId()}`\n\n return (\n <header {...props} className={classNames(style(\"root\"), className)} data-rly-diff-layout={layout}>\n {/* The container's own child, so the narrow layout below can stack thesis and progress. */}\n <div className={style(\"summary\")}>\n <section className={style(\"thesis\")}>\n <h1>{visibleHeading}</h1>\n <p>{selectedFileLabel === undefined ? \"All changed files\" : selectedFileLabel}</p>\n </section>\n\n <section aria-labelledby={progressId} className={style(\"progress\")}>\n {/* One line of words in the flow, never a display figure that can run over the title. */}\n <span className={style(\"progressCopy\")} id={progressId}>\n {totalCount === 0\n ? \"No files to index\"\n : indexedCount === totalCount\n ? `All ${totalCount} files indexed`\n : `${indexedCount} of ${totalCount} files indexed`}\n </span>\n <progress max={Math.max(totalCount, 1)} value={indexedCount} />\n </section>\n </div>\n\n <div className={style(\"controls\")}>\n <div aria-label=\"Diff layout\" className={style(\"group\")} role=\"group\">\n {layouts.map((option) => (\n <button aria-pressed={layout === option} key={option} onClick={() => onLayoutChange(option)} type=\"button\">\n {titleCase(option)}\n </button>\n ))}\n </div>\n <button\n aria-pressed={isWrapped}\n className={style(\"standalone\")}\n onClick={() => onWrapChange(!isWrapped)}\n type=\"button\"\n >\n Wrap lines\n </button>\n <div aria-label=\"Finding filter\" className={style(\"group\")} role=\"group\">\n {findingFilters.map((filter) => (\n <button\n aria-pressed={findingFilter === filter}\n key={filter}\n onClick={() => onFindingFilterChange(filter)}\n type=\"button\"\n >\n {titleCase(filter)}\n </button>\n ))}\n </div>\n </div>\n </header>\n )\n}\n","import type { ComponentPropsWithRef, ReactElement, ReactNode } from \"react\"\nimport { classNames, cssClass, requireText } from \"../internal/component.js\"\nimport styles from \"./DiffWorkbench.module.css\"\n\nconst style = (name: string): string => cssClass(styles, name)\n\n/** The application-controlled file scope shown by the workbench. */\nexport type RlyDiffWorkbenchScope =\n | { readonly label: string; readonly mode: \"all-files\" }\n | { readonly fileId: string; readonly label: string; readonly mode: \"selected-file\" }\n\n/** One stable semantic finding slot, independent from virtualized line annotations. */\nexport interface RlyDiffWorkbenchFinding {\n readonly content: ReactNode\n readonly id: string\n}\n\n/** Presentation-only slots for a complete diff review surface. */\nexport type DiffWorkbenchProps = Omit<ComponentPropsWithRef<\"section\">, \"aria-label\" | \"children\"> & {\n readonly emptyFindings?: ReactNode\n readonly findings: ReadonlyArray<RlyDiffWorkbenchFinding>\n readonly findingsLabel?: string\n readonly header: ReactNode\n readonly inventory: ReactNode\n readonly inventoryLabel?: string\n readonly label: string\n readonly onShowAllFiles?: () => void\n readonly scope: RlyDiffWorkbenchScope\n readonly statusNotice?: ReactNode\n readonly viewer: ReactNode\n readonly viewerLabel?: string\n}\n\nconst validateFindings = (findings: ReadonlyArray<RlyDiffWorkbenchFinding>): void => {\n const ids = new Set<string>()\n for (const finding of findings) {\n const id = requireText(finding.id, \"DiffWorkbench finding id\")\n if (ids.has(id)) throw new Error(`DiffWorkbench finding ids must be unique: ${id}`)\n ids.add(id)\n }\n}\n\n/** Compose complete inventory, renderer, and semantic evidence without owning application state. */\nexport const DiffWorkbench = ({\n className,\n emptyFindings = \"No findings match this view.\",\n findings,\n findingsLabel = \"Semantic findings\",\n header,\n inventory,\n inventoryLabel = \"Changed files\",\n label,\n onShowAllFiles,\n scope,\n statusNotice,\n viewer,\n viewerLabel = \"Code changes\",\n ...props\n}: DiffWorkbenchProps): ReactElement => {\n const visibleLabel = requireText(label, \"DiffWorkbench label\")\n const visibleScopeLabel = requireText(scope.label, \"DiffWorkbench scope label\")\n const visibleInventoryLabel = requireText(inventoryLabel, \"DiffWorkbench inventoryLabel\")\n const visibleViewerLabel = requireText(viewerLabel, \"DiffWorkbench viewerLabel\")\n const visibleFindingsLabel = requireText(findingsLabel, \"DiffWorkbench findingsLabel\")\n if (scope.mode === \"selected-file\") {\n requireText(scope.fileId, \"DiffWorkbench selected file id\")\n if (onShowAllFiles === undefined) {\n throw new Error(\"DiffWorkbench selected-file scope requires onShowAllFiles\")\n }\n }\n validateFindings(findings)\n\n return (\n <section\n {...props}\n aria-label={visibleLabel}\n className={classNames(style(\"root\"), className)}\n data-rly-diff-scope={scope.mode}\n {...(scope.mode === \"selected-file\" ? { \"data-rly-diff-selected-file\": scope.fileId } : {})}\n >\n <div className={style(\"header\")} data-rly-diff-workbench-slot=\"header\">\n {header}\n </div>\n\n <div className={style(\"body\")}>\n <section\n aria-label={visibleInventoryLabel}\n className={style(\"inventory\")}\n data-rly-diff-workbench-slot=\"inventory\"\n >\n {inventory}\n </section>\n\n <div className={style(\"review\")}>\n <header className={style(\"scope\")}>\n <span className={style(\"scopeLabel\")}>{scope.mode === \"all-files\" ? \"All files\" : \"Selected file\"}</span>\n <strong className={style(\"scopeValue\")}>{visibleScopeLabel}</strong>\n {scope.mode === \"selected-file\" ? (\n <button className={style(\"showAll\")} onClick={onShowAllFiles} type=\"button\">\n Show all files\n </button>\n ) : null}\n </header>\n {statusNotice === undefined ? null : (\n <div aria-live=\"polite\" className={style(\"notice\")} data-rly-diff-workbench-slot=\"status\" role=\"status\">\n {statusNotice}\n </div>\n )}\n <section aria-label={visibleViewerLabel} className={style(\"viewer\")} data-rly-diff-workbench-slot=\"viewer\">\n {viewer}\n </section>\n </div>\n\n <aside aria-label={visibleFindingsLabel} className={style(\"findings\")} data-rly-diff-workbench-slot=\"findings\">\n <header className={style(\"findingsHeader\")}>\n {/* The heading and its count in words: no eyebrow, no display figure. */}\n <h2>{visibleFindingsLabel}</h2>\n <span>{findings.length === 1 ? \"1 finding\" : `${findings.length} findings`}</span>\n </header>\n {findings.length === 0 ? (\n <div className={style(\"empty\")}>{emptyFindings}</div>\n ) : (\n <ol aria-label={`${visibleFindingsLabel} list`} className={style(\"findingList\")} tabIndex={0}>\n {findings.map((finding) => (\n <li className={style(\"findingItem\")} key={finding.id}>\n {finding.content}\n </li>\n ))}\n </ol>\n )}\n </aside>\n </div>\n </section>\n )\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@knpkv/rly",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.0",
|
|
4
4
|
"description": "Release-oriented design system for human and agent collaboration",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "knpkv",
|
|
@@ -115,6 +115,7 @@
|
|
|
115
115
|
"codegen:check": "tsx scripts/generate-contract.ts check",
|
|
116
116
|
"lint": "eslint \"{src,test,scripts,generated,manifest,stories,visual,.storybook}/**/*.{ts,tsx}\" component-manifest.ts vite.config.ts vite.bounded.config.ts vitest.config.ts vitest.storybook.config.ts playwright.config.ts && pnpm lint:colors && pnpm lint:stripes",
|
|
117
117
|
"lint:colors": "tsx scripts/tokens/lint-colors.ts",
|
|
118
|
+
"lint:focus-rings": "tsx scripts/tokens/lint-focus-rings.ts",
|
|
118
119
|
"lint:stripes": "tsx scripts/tokens/lint-stripes.ts",
|
|
119
120
|
"scaffold": "tsx scripts/scaffold-component.ts",
|
|
120
121
|
"storybook": "storybook dev --host 127.0.0.1 --port 6006 --exact-port --no-open --no-version-updates",
|